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