power_manager_client.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/message_loop.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/platform_thread.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/power_manager/input_event.pb.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/power_manager/peripheral_battery_status.pb.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/power_manager/policy.pb.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/power_manager/suspend.pb.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/bus.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/message.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_proxy.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Maximum amount of time that the power manager will wait for Chrome to
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// say that it's ready for the system to be suspended, in milliseconds.
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kSuspendDelayTimeoutMs = 5000;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Human-readable description of Chrome's suspend delay.
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kSuspendDelayDescription[] = "chrome";
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The PowerManagerClient implementation used in production.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PowerManagerClientImpl : public PowerManagerClient {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit PowerManagerClientImpl(dbus::Bus* bus)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : origin_thread_id_(base::PlatformThread::CurrentId()),
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager_proxy_(NULL),
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        suspend_delay_id_(-1),
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        has_suspend_delay_id_(false),
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        pending_suspend_id_(-1),
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        suspend_is_pending_(false),
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        num_pending_suspend_readiness_callbacks_(0),
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        last_is_projecting_(false),
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        weak_ptr_factory_(this) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_ = bus->GetObjectProxy(
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerServiceName,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectPath(power_manager::kPowerManagerServicePath));
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager_proxy_->SetNameOwnerChangedCallback(
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::NameOwnerChangedReceived,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Monitor the D-Bus signal for brightness changes. Only the power
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // manager knows the actual brightness level. We don't cache the
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // brightness level in Chrome as it'll make things less reliable.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kBrightnessChangedSignal,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::BrightnessChangedReceived,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        power_manager::kPeripheralBatteryStatusSignal,
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::PeripheralBatteryStatusReceived,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        power_manager::kPowerSupplyPollSignal,
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::PowerSupplyPollReceived,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        power_manager::kIdleNotifySignal,
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::IdleNotifySignalReceived,
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kInputEventSignal,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::InputEventReceived,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kSuspendStateChangedSignal,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SuspendStateChangedReceived,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kSuspendImminentSignal,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &PowerManagerClientImpl::SuspendImminentReceived,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            weak_ptr_factory_.GetWeakPtr()),
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kPowerManagerInterface,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kIdleActionImminentSignal,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &PowerManagerClientImpl::IdleActionImminentReceived,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            weak_ptr_factory_.GetWeakPtr()),
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager_proxy_->ConnectToSignal(
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kPowerManagerInterface,
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kIdleActionDeferredSignal,
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &PowerManagerClientImpl::IdleActionDeferredReceived,
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            weak_ptr_factory_.GetWeakPtr()),
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&PowerManagerClientImpl::SignalConnected,
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RegisterSuspendDelay();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~PowerManagerClientImpl() {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Here we should unregister suspend notifications from powerd,
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // however:
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // - The lifetime of the PowerManagerClientImpl can extend past that of
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //   the objectproxy,
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // - power_manager can already detect that the client is gone and
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //   unregister our suspend delay.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PowerManagerClient overrides:
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(observer);  // http://crbug.com/119976
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.AddObserver(observer);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.RemoveObserver(observer);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HasObserver(Observer* observer) OVERRIDE {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return observers_.HasObserver(observer);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecreaseScreenBrightness(bool allow_off) OVERRIDE {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kDecreaseScreenBrightness);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendBool(allow_off);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void IncreaseScreenBrightness() OVERRIDE {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimpleMethodCallToPowerManager(power_manager::kIncreaseScreenBrightness);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecreaseKeyboardBrightness() OVERRIDE {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimpleMethodCallToPowerManager(power_manager::kDecreaseKeyboardBrightness);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void IncreaseKeyboardBrightness() OVERRIDE {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimpleMethodCallToPowerManager(power_manager::kIncreaseKeyboardBrightness);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetScreenBrightnessPercent(double percent,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          bool gradual) OVERRIDE {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kSetScreenBrightnessPercent);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendDouble(percent);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendInt32(
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gradual ?
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kBrightnessTransitionGradual :
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kBrightnessTransitionInstant);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetScreenBrightnessPercent(
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GetScreenBrightnessPercentCallback& callback) OVERRIDE {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 power_manager::kGetScreenBrightnessPercent);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::OnGetScreenBrightnessPercent,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(), callback));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void RequestStatusUpdate() OVERRIDE {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kGetPowerSupplyPropertiesMethod);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PowerManagerClientImpl::OnGetPowerSupplyPropertiesMethod,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestRestart() OVERRIDE {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimpleMethodCallToPowerManager(power_manager::kRequestRestartMethod);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestShutdown() OVERRIDE {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimpleMethodCallToPowerManager(power_manager::kRequestShutdownMethod);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestIdleNotification(int64 threshold) OVERRIDE {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 power_manager::kRequestIdleNotification);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendInt64(threshold);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void NotifyUserActivity() OVERRIDE {
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SimpleMethodCallToPowerManager(power_manager::kHandleUserActivityMethod);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void NotifyVideoActivity(bool is_fullscreen) OVERRIDE {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kHandleVideoActivityMethod);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writer.AppendBool(is_fullscreen);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetPolicy(
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const power_manager::PowerManagementPolicy& policy) OVERRIDE {
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MethodCall method_call(
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kPowerManagerInterface,
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kSetPolicyMethod);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!writer.AppendProtoAsArrayOfBytes(policy)) {
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Error calling " << power_manager::kSetPolicyMethod;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetIsProjecting(bool is_projecting) OVERRIDE {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kPowerManagerInterface,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        power_manager::kSetIsProjectingMethod);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendBool(is_projecting);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    last_is_projecting_ = is_projecting;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual base::Closure GetSuspendReadinessCallback() OVERRIDE {
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(OnOriginThread());
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(suspend_is_pending_);
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_pending_suspend_readiness_callbacks_++;
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::Bind(&PowerManagerClientImpl::HandleObserverSuspendReadiness,
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      weak_ptr_factory_.GetWeakPtr(), pending_suspend_id_);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns true if the current thread is the origin thread.
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool OnOriginThread() {
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::PlatformThread::CurrentId() == origin_thread_id_;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when a dbus signal is initially connected.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SignalConnected(const std::string& interface_name,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const std::string& signal_name,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       bool success) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG_IF(WARNING, !success) << "Failed to connect to signal "
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              << signal_name << ".";
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make a method call to power manager with no arguments and no response.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SimpleMethodCallToPowerManager(const std::string& method_name) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 method_name);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    power_manager_proxy_->CallMethod(
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void NameOwnerChangedReceived(dbus::Signal* signal) {
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Power manager restarted";
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RegisterSuspendDelay();
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetIsProjecting(last_is_projecting_);
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, PowerManagerRestarted());
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BrightnessChangedReceived(dbus::Signal* signal) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(signal);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 brightness_level = 0;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool user_initiated = 0;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(reader.PopInt32(&brightness_level) &&
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reader.PopBool(&user_initiated))) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Brightness changed signal had incorrect parameters: "
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << signal->ToString();
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Brightness changed to " << brightness_level
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ": user initiated " << user_initiated;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      BrightnessChanged(brightness_level, user_initiated));
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void PeripheralBatteryStatusReceived(dbus::Signal* signal) {
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(signal);
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    power_manager::PeripheralBatteryStatus protobuf_status;
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!reader.PopArrayOfBytesAsProto(&protobuf_status)) {
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(ERROR) << "Unable to decode protocol buffer from "
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 << power_manager::kPeripheralBatteryStatusSignal << " signal";
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string path = protobuf_status.path();
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string name = protobuf_status.name();
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int level = protobuf_status.has_level() ? protobuf_status.level() : -1;
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VLOG(1) << "Device battery status received " << level
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            << " for " << name << " at " << path;
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_,
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      PeripheralBatteryStatusReceived(path, name, level));
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void PowerSupplyPollReceived(dbus::Signal* signal) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Received power supply poll signal.";
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    dbus::MessageReader reader(signal);
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    power_manager::PowerSupplyProperties protobuf;
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (reader.PopArrayOfBytesAsProto(&protobuf)) {
375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(protobuf));
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << "Unable to decode "
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 << power_manager::kPowerSupplyPollSignal << "signal";
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnGetPowerSupplyPropertiesMethod(dbus::Response* response) {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response) {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Error calling "
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << power_manager::kGetPowerSupplyPropertiesMethod;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(response);
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    power_manager::PowerSupplyProperties protobuf;
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (reader.PopArrayOfBytesAsProto(&protobuf)) {
392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(protobuf));
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << "Unable to decode "
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << power_manager::kGetPowerSupplyPropertiesMethod
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 << " response";
39790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnGetScreenBrightnessPercent(
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const GetScreenBrightnessPercentCallback& callback,
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dbus::Response* response) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response) {
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Error calling "
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kGetScreenBrightnessPercent;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(response);
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double percent = 0.0;
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.PopDouble(&percent))
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Error reading response from powerd: "
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << response->ToString();
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(percent);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnRegisterSuspendDelayReply(dbus::Response* response) {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response) {
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Error calling "
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kRegisterSuspendDelayMethod;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(response);
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::RegisterSuspendDelayReply protobuf;
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.PopArrayOfBytesAsProto(&protobuf)) {
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Unable to parse reply from "
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kRegisterSuspendDelayMethod;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    suspend_delay_id_ = protobuf.delay_id();
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    has_suspend_delay_id_ = true;
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Registered suspend delay " << suspend_delay_id_;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void IdleNotifySignalReceived(dbus::Signal* signal) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(signal);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 threshold = 0;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!reader.PopInt64(&threshold)) {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Idle Notify signal had incorrect parameters: "
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << signal->ToString();
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_GT(threshold, 0);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Idle Notify: " << threshold;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, IdleNotify(threshold));
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SuspendImminentReceived(dbus::Signal* signal) {
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!has_suspend_delay_id_) {
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Received unrequested "
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kSuspendImminentSignal << " signal";
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageReader reader(signal);
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::SuspendImminent protobuf_imminent;
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.PopArrayOfBytesAsProto(&protobuf_imminent)) {
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Unable to decode protocol buffer from "
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kSuspendImminentSignal << " signal";
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (suspend_is_pending_) {
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(WARNING) << "Got " << power_manager::kSuspendImminentSignal
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << " signal about pending suspend attempt "
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << protobuf_imminent.suspend_id() << " while still waiting "
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << "on attempt " << pending_suspend_id_;
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_suspend_id_ = protobuf_imminent.suspend_id();
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    suspend_is_pending_ = true;
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_pending_suspend_readiness_callbacks_ = 0;
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, SuspendImminent());
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MaybeReportSuspendReadiness();
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void IdleActionImminentReceived(dbus::Signal* signal) {
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, IdleActionImminent());
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void IdleActionDeferredReceived(dbus::Signal* signal) {
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, IdleActionDeferred());
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InputEventReceived(dbus::Signal* signal) {
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageReader reader(signal);
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::InputEvent proto;
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.PopArrayOfBytesAsProto(&proto)) {
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Unable to decode protocol buffer from "
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kInputEventSignal << " signal";
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeTicks timestamp =
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeTicks::FromInternalValue(proto.timestamp());
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Got " << power_manager::kInputEventSignal << " signal:"
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << " type=" << proto.type() << " timestamp=" << proto.timestamp();
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (proto.type()) {
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::InputEvent_Type_POWER_BUTTON_DOWN:
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::InputEvent_Type_POWER_BUTTON_UP: {
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bool down =
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            (proto.type() == power_manager::InputEvent_Type_POWER_BUTTON_DOWN);
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FOR_EACH_OBSERVER(PowerManagerClient::Observer, observers_,
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          PowerButtonEventReceived(down, timestamp));
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::InputEvent_Type_LID_OPEN:
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::InputEvent_Type_LID_CLOSED: {
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bool open =
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            (proto.type() == power_manager::InputEvent_Type_LID_OPEN);
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FOR_EACH_OBSERVER(PowerManagerClient::Observer, observers_,
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          LidEventReceived(open, timestamp));
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SuspendStateChangedReceived(dbus::Signal* signal) {
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageReader reader(signal);
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::SuspendState proto;
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!reader.PopArrayOfBytesAsProto(&proto)) {
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Unable to decode protocol buffer from "
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kSuspendStateChangedSignal << " signal";
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "Got " << power_manager::kSuspendStateChangedSignal << " signal:"
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << " type=" << proto.type() << " wall_time=" << proto.wall_time();
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Time wall_time =
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Time::FromInternalValue(proto.wall_time());
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (proto.type()) {
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::SuspendState_Type_SUSPEND_TO_MEMORY:
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        last_suspend_wall_time_ = wall_time;
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case power_manager::SuspendState_Type_RESUME:
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FOR_EACH_OBSERVER(
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            PowerManagerClient::Observer, observers_,
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            SystemResumed(wall_time - last_suspend_wall_time_));
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Registers a suspend delay with the power manager.  This is usually
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // only called at startup, but if the power manager restarts, we need to
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // create a new delay.
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void RegisterSuspendDelay() {
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Throw out any old delay that was registered.
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    suspend_delay_id_ = -1;
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    has_suspend_delay_id_ = false;
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MethodCall method_call(
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kPowerManagerInterface,
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kRegisterSuspendDelayMethod);
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageWriter writer(&method_call);
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::RegisterSuspendDelayRequest protobuf_request;
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta timeout =
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(kSuspendDelayTimeoutMs);
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protobuf_request.set_timeout(timeout.ToInternalValue());
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protobuf_request.set_description(kSuspendDelayDescription);
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!writer.AppendProtoAsArrayOfBytes(protobuf_request)) {
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Error constructing message for "
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kRegisterSuspendDelayMethod;
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager_proxy_->CallMethod(
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &method_call,
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &PowerManagerClientImpl::OnRegisterSuspendDelayReply,
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            weak_ptr_factory_.GetWeakPtr()));
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Records the fact that an observer has finished doing asynchronous work
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // that was blocking a pending suspend attempt and possibly reports
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // suspend readiness to powerd.  Called by callbacks returned via
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // GetSuspendReadinessCallback().
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void HandleObserverSuspendReadiness(int32 suspend_id) {
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(OnOriginThread());
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!suspend_is_pending_ || suspend_id != pending_suspend_id_)
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    num_pending_suspend_readiness_callbacks_--;
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MaybeReportSuspendReadiness();
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Reports suspend readiness to powerd if no observers are still holding
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // suspend readiness callbacks.
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void MaybeReportSuspendReadiness() {
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!suspend_is_pending_ || num_pending_suspend_readiness_callbacks_ > 0)
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MethodCall method_call(
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kPowerManagerInterface,
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_manager::kHandleSuspendReadinessMethod);
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageWriter writer(&method_call);
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager::SuspendReadinessInfo protobuf_request;
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protobuf_request.set_delay_id(suspend_delay_id_);
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    protobuf_request.set_suspend_id(pending_suspend_id_);
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_suspend_id_ = -1;
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    suspend_is_pending_ = false;
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!writer.AppendProtoAsArrayOfBytes(protobuf_request)) {
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Error constructing message for "
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << power_manager::kHandleSuspendReadinessMethod;
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    power_manager_proxy_->CallMethod(
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &method_call,
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dbus::ObjectProxy::EmptyResponseCallback());
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Origin thread (i.e. the UI thread in production).
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::PlatformThreadId origin_thread_id_;
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus::ObjectProxy* power_manager_proxy_;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObserverList<Observer> observers_;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The delay_id_ obtained from the RegisterSuspendDelay request.
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 suspend_delay_id_;
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool has_suspend_delay_id_;
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // powerd-supplied ID corresponding to an imminent suspend attempt that is
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // currently being delayed.
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 pending_suspend_id_;
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool suspend_is_pending_;
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Number of callbacks that have been returned by
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // GetSuspendReadinessCallback() during the currently-pending suspend
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // attempt but have not yet been called.
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int num_pending_suspend_readiness_callbacks_;
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Wall time from the latest signal telling us that the system was about to
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // suspend to memory.
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Time last_suspend_wall_time_;
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
64390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Last state passed to SetIsProjecting().
64490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool last_is_projecting_;
64590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: This should remain the last member so it'll be destroyed and
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invalidate its weak pointers before any other members are destroyed.
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<PowerManagerClientImpl> weak_ptr_factory_;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PowerManagerClientImpl);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The PowerManagerClient implementation used on Linux desktop,
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which does nothing.
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PowerManagerClientStubImpl : public PowerManagerClient {
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PowerManagerClientStubImpl()
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : discharging_(true),
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        battery_percentage_(40),
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        brightness_(50.0),
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        pause_count_(2),
662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        cycle_count_(0),
663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        weak_ptr_factory_(this) {
664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const int kStatusUpdateMs = 1000;
665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    update_timer_.Start(FROM_HERE,
666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(kStatusUpdateMs), this,
667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &PowerManagerClientStubImpl::UpdateStatus);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~PowerManagerClientStubImpl() {}
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PowerManagerClient overrides:
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.AddObserver(observer);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.RemoveObserver(observer);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HasObserver(Observer* observer) OVERRIDE {
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return observers_.HasObserver(observer);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecreaseScreenBrightness(bool allow_off) OVERRIDE {
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to descrease screen brightness";
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetBrightness(brightness_ - 5.0, true);
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void IncreaseScreenBrightness() OVERRIDE {
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to increase screen brightness";
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetBrightness(brightness_ + 5.0, true);
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetScreenBrightnessPercent(double percent,
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          bool gradual) OVERRIDE {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to set screen brightness to " << percent << "% "
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << (gradual ? "gradually" : "instantaneously");
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetBrightness(percent, false);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetScreenBrightnessPercent(
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GetScreenBrightnessPercentCallback& callback) OVERRIDE {
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run(brightness_);
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DecreaseKeyboardBrightness() OVERRIDE {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to descrease keyboard brightness";
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void IncreaseKeyboardBrightness() OVERRIDE {
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requested to increase keyboard brightness";
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void RequestStatusUpdate() OVERRIDE {
717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::MessageLoop::current()->PostTask(FROM_HERE,
718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::Bind(&PowerManagerClientStubImpl::UpdateStatus,
719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestRestart() OVERRIDE {}
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestShutdown() OVERRIDE {}
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void RequestIdleNotification(int64 threshold) OVERRIDE {
726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&PowerManagerClientStubImpl::TriggerIdleNotify,
729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(), threshold),
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(threshold));
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void NotifyUserActivity() OVERRIDE {}
734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void NotifyVideoActivity(bool is_fullscreen) OVERRIDE {}
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetPolicy(
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const power_manager::PowerManagementPolicy& policy) OVERRIDE {}
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetIsProjecting(bool is_projecting) OVERRIDE {}
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual base::Closure GetSuspendReadinessCallback() OVERRIDE {
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return base::Closure();
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void UpdateStatus() {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pause_count_ > 0) {
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pause_count_--;
746eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (pause_count_ == 2)
747eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        discharging_ = !discharging_;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (discharging_)
750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        battery_percentage_ -= (battery_percentage_ <= 10 ? 1 : 10);
751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      else
752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        battery_percentage_ += (battery_percentage_ >= 10 ? 10 : 1);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      battery_percentage_ = std::min(std::max(battery_percentage_, 0), 100);
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We pause at 0 and 100% so that it's easier to check those conditions.
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (battery_percentage_ == 0 || battery_percentage_ == 100) {
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pause_count_ = 4;
757c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (battery_percentage_ == 100)
758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          cycle_count_ = (cycle_count_ + 1) % 3;
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
762eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const int kSecondsToEmptyFullBattery = 3 * 60 * 60;  // 3 hours.
763a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int64 remaining_battery_time =
764a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        std::max(1, battery_percentage_ * kSecondsToEmptyFullBattery / 100);
765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
766eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    props_.Clear();
767eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
768eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    switch (cycle_count_) {
769eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      case 0:
770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Say that the system is charging with AC connected and
771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // discharging without any charger connected.
772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        props_.set_external_power(discharging_ ?
773eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED :
774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            power_manager::PowerSupplyProperties_ExternalPower_AC);
775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      case 1:
777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Say that the system is both charging and discharging on USB
778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // (i.e. a low-power charger).
779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        props_.set_external_power(
780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            power_manager::PowerSupplyProperties_ExternalPower_USB);
781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      case 2:
783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Say that the system is both charging and discharging on AC.
784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        props_.set_external_power(
785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            power_manager::PowerSupplyProperties_ExternalPower_AC);
786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      default:
788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        NOTREACHED() << "Unhandled cycle " << cycle_count_;
789eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
790eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (battery_percentage_ == 100 && !discharging_) {
792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_state(
793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          power_manager::PowerSupplyProperties_BatteryState_FULL);
794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else if (!discharging_) {
795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_state(
796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          power_manager::PowerSupplyProperties_BatteryState_CHARGING);
797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_time_to_full_sec(std::max(static_cast<int64>(1),
798eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kSecondsToEmptyFullBattery - remaining_battery_time));
799eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else {
800eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_state(
801eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
802eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      props_.set_battery_time_to_empty_sec(remaining_battery_time);
803eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
805eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    props_.set_battery_percent(battery_percentage_);
806eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    props_.set_is_calculating_battery_time(pause_count_ > 1);
807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
808eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(props_));
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetBrightness(double percent, bool user_initiated) {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    brightness_ = std::min(std::max(0.0, percent), 100.0);
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int brightness_level = static_cast<int>(brightness_);
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_,
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      BrightnessChanged(brightness_level, user_initiated));
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void TriggerIdleNotify(int64 threshold) {
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, IdleNotify(threshold));
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool discharging_;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int battery_percentage_;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double brightness_;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pause_count_;
826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int cycle_count_;
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObserverList<Observer> observers_;
828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::RepeatingTimer<PowerManagerClientStubImpl> update_timer_;
829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  power_manager::PowerSupplyProperties props_;
830868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
831868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Note: This should remain the last member so it'll be destroyed and
832868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // invalidate its weak pointers before any other members are destroyed.
833868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::WeakPtrFactory<PowerManagerClientStubImpl> weak_ptr_factory_;
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PowerManagerClient::PowerManagerClient() {
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PowerManagerClient::~PowerManagerClient() {
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PowerManagerClient* PowerManagerClient::Create(
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DBusClientImplementationType type,
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::Bus* bus) {
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new PowerManagerClientImpl(bus);
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new PowerManagerClientStubImpl();
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
853