1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "chromeos/dbus/power/power_manager_client.h"
- #include <stdint.h>
- #include <algorithm>
- #include <memory>
- #include <unordered_map>
- #include <utility>
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/command_line.h"
- #include "base/format_macros.h"
- #include "base/logging.h"
- #include "base/observer_list.h"
- #include "base/power_monitor/power_monitor.h"
- #include "base/power_monitor/power_monitor_device_source.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/string_split.h"
- #include "base/threading/platform_thread.h"
- #include "base/time/time.h"
- #include "base/timer/timer.h"
- #include "base/unguessable_token.h"
- #include "chromeos/dbus/constants/dbus_switches.h"
- #include "chromeos/dbus/power/fake_power_manager_client.h"
- #include "chromeos/dbus/power_manager/backlight.pb.h"
- #include "chromeos/dbus/power_manager/idle.pb.h"
- #include "chromeos/dbus/power_manager/input_event.pb.h"
- #include "chromeos/dbus/power_manager/peripheral_battery_status.pb.h"
- #include "chromeos/dbus/power_manager/switch_states.pb.h"
- #include "chromeos/dbus/power_manager/thermal.pb.h"
- #include "components/device_event_log/device_event_log.h"
- #include "dbus/bus.h"
- #include "dbus/message.h"
- #include "dbus/object_path.h"
- #include "dbus/object_proxy.h"
- namespace chromeos {
- namespace {
- PowerManagerClient* g_instance = nullptr;
- // Maximum amount of time that the power manager will wait for Chrome to
- // say that it's ready for the system to be suspended, in milliseconds.
- const int kSuspendDelayTimeoutMs = 5000;
- // Human-readable description of Chrome's suspend delay.
- const char kSuspendDelayDescription[] = "chrome";
- // Returns a modified version of |proto| where fields are consistent.
- power_manager::PowerSupplyProperties SanitizePowerSupplyProperties(
- const power_manager::PowerSupplyProperties& proto) {
- power_manager::PowerSupplyProperties sanitized = proto;
- if (sanitized.battery_state() ==
- power_manager::PowerSupplyProperties_BatteryState_FULL) {
- sanitized.set_battery_percent(100.0);
- }
- if (!sanitized.is_calculating_battery_time()) {
- const bool on_line_power =
- sanitized.external_power() !=
- power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED;
- if ((on_line_power && sanitized.battery_time_to_full_sec() < 0) ||
- (!on_line_power && sanitized.battery_time_to_empty_sec() < 0)) {
- sanitized.set_is_calculating_battery_time(true);
- }
- }
- return sanitized;
- }
- // Converts a LidState value from a power_manager::SwitchStates proto to the
- // corresponding PowerManagerClient::LidState value.
- PowerManagerClient::LidState GetLidStateFromProtoEnum(
- power_manager::SwitchStates::LidState state) {
- switch (state) {
- case power_manager::SwitchStates_LidState_OPEN:
- return PowerManagerClient::LidState::OPEN;
- case power_manager::SwitchStates_LidState_CLOSED:
- return PowerManagerClient::LidState::CLOSED;
- case power_manager::SwitchStates_LidState_NOT_PRESENT:
- return PowerManagerClient::LidState::NOT_PRESENT;
- }
- NOTREACHED() << "Unhandled lid state " << state;
- return PowerManagerClient::LidState::NOT_PRESENT;
- }
- // Converts a TabletMode value from a power_manager::SwitchStates proto to the
- // corresponding PowerManagerClient::TabletMode value.
- PowerManagerClient::TabletMode GetTabletModeFromProtoEnum(
- power_manager::SwitchStates::TabletMode mode) {
- switch (mode) {
- case power_manager::SwitchStates_TabletMode_ON:
- return PowerManagerClient::TabletMode::ON;
- case power_manager::SwitchStates_TabletMode_OFF:
- return PowerManagerClient::TabletMode::OFF;
- case power_manager::SwitchStates_TabletMode_UNSUPPORTED:
- return PowerManagerClient::TabletMode::UNSUPPORTED;
- }
- NOTREACHED() << "Unhandled tablet mode " << mode;
- return PowerManagerClient::TabletMode::UNSUPPORTED;
- }
- // Converts a ThermalState value from a power_manager::ThermalEvent proto to the
- // corresponding base::PowerThermalObserver::DeviceThermalState value.
- base::PowerThermalObserver::DeviceThermalState GetThermalStateFromProtoEnum(
- power_manager::ThermalEvent::ThermalState state) {
- switch (state) {
- case power_manager::ThermalEvent_ThermalState_UNKNOWN:
- return base::PowerThermalObserver::DeviceThermalState::kUnknown;
- case power_manager::ThermalEvent_ThermalState_NOMINAL:
- return base::PowerThermalObserver::DeviceThermalState::kNominal;
- case power_manager::ThermalEvent_ThermalState_FAIR:
- return base::PowerThermalObserver::DeviceThermalState::kFair;
- case power_manager::ThermalEvent_ThermalState_SERIOUS:
- return base::PowerThermalObserver::DeviceThermalState::kSerious;
- case power_manager::ThermalEvent_ThermalState_CRITICAL:
- return base::PowerThermalObserver::DeviceThermalState::kCritical;
- }
- NOTREACHED() << "Unhandled thermal state " << state;
- return base::PowerThermalObserver::DeviceThermalState::kUnknown;
- }
- // Callback for D-Bus call made in |CreateArcTimers|.
- void OnCreateArcTimersDBusMethod(
- DBusMethodCallback<std::vector<PowerManagerClient::TimerId>> callback,
- dbus::Response* response) {
- if (response == nullptr) {
- std::move(callback).Run(absl::nullopt);
- return;
- }
- dbus::MessageReader reader(response);
- dbus::MessageReader array_reader(nullptr);
- if (!reader.PopArray(&array_reader)) {
- POWER_LOG(ERROR) << "No timer ids returned";
- std::move(callback).Run(absl::nullopt);
- return;
- }
- std::vector<PowerManagerClient::TimerId> timer_ids;
- while (array_reader.HasMoreData()) {
- int32_t timer_id;
- if (!array_reader.PopInt32(&timer_id)) {
- POWER_LOG(ERROR) << "Failed to pop timer id";
- std::move(callback).Run(absl::nullopt);
- return;
- }
- timer_ids.push_back(timer_id);
- }
- std::move(callback).Run(std::move(timer_ids));
- }
- // Callback for D-Bus call made in |StartArcTimer| and |DeleteArcTimers|.
- void OnVoidDBusMethod(VoidDBusMethodCallback callback,
- dbus::Response* response) {
- std::move(callback).Run(response != nullptr);
- }
- } // namespace
- // The PowerManagerClient implementation used in production.
- class PowerManagerClientImpl : public PowerManagerClient {
- public:
- PowerManagerClientImpl()
- : origin_thread_id_(base::PlatformThread::CurrentId()) {}
- PowerManagerClientImpl(const PowerManagerClientImpl&) = delete;
- PowerManagerClientImpl& operator=(const PowerManagerClientImpl&) = delete;
- ~PowerManagerClientImpl() override {
- // Here we should unregister suspend notifications from powerd,
- // however:
- // - The lifetime of the PowerManagerClientImpl can extend past that of
- // the objectproxy,
- // - power_manager can already detect that the client is gone and
- // unregister our suspend delay.
- }
- void Init(dbus::Bus* bus) {
- power_manager_proxy_ = bus->GetObjectProxy(
- power_manager::kPowerManagerServiceName,
- dbus::ObjectPath(power_manager::kPowerManagerServicePath));
- power_manager_proxy_->SetNameOwnerChangedCallback(
- base::BindRepeating(&PowerManagerClientImpl::NameOwnerChangedReceived,
- weak_ptr_factory_.GetWeakPtr()));
- power_manager_proxy_->WaitForServiceToBeAvailable(
- base::BindOnce(&PowerManagerClientImpl::NotifyServiceBecameAvailable,
- weak_ptr_factory_.GetWeakPtr()));
- // Listen to D-Bus signals emitted by powerd.
- typedef void (PowerManagerClientImpl::*SignalMethod)(dbus::Signal*);
- const std::pair<const char*, SignalMethod> kSignalMethods[] = {
- {power_manager::kScreenBrightnessChangedSignal,
- &PowerManagerClientImpl::ScreenBrightnessChangedReceived},
- {power_manager::kAmbientColorTemperatureChangedSignal,
- &PowerManagerClientImpl::AmbientColorTemperatureChangedReceived},
- {power_manager::kKeyboardBrightnessChangedSignal,
- &PowerManagerClientImpl::KeyboardBrightnessChangedReceived},
- {power_manager::kScreenIdleStateChangedSignal,
- &PowerManagerClientImpl::ScreenIdleStateChangedReceived},
- {power_manager::kInactivityDelaysChangedSignal,
- &PowerManagerClientImpl::InactivityDelaysChangedReceived},
- {power_manager::kPeripheralBatteryStatusSignal,
- &PowerManagerClientImpl::PeripheralBatteryStatusReceived},
- {power_manager::kPowerSupplyPollSignal,
- &PowerManagerClientImpl::PowerSupplyPollReceived},
- {power_manager::kInputEventSignal,
- &PowerManagerClientImpl::InputEventReceived},
- {power_manager::kSuspendImminentSignal,
- &PowerManagerClientImpl::SuspendImminentReceived},
- {power_manager::kSuspendDoneSignal,
- &PowerManagerClientImpl::SuspendDoneReceived},
- {power_manager::kDarkSuspendImminentSignal,
- &PowerManagerClientImpl::DarkSuspendImminentReceived},
- {power_manager::kIdleActionImminentSignal,
- &PowerManagerClientImpl::IdleActionImminentReceived},
- {power_manager::kIdleActionDeferredSignal,
- &PowerManagerClientImpl::IdleActionDeferredReceived},
- {power_manager::kThermalEventSignal,
- &PowerManagerClientImpl::ThermalEventReceived},
- };
- auto on_connected_callback =
- base::BindRepeating(&PowerManagerClientImpl::SignalConnected,
- weak_ptr_factory_.GetWeakPtr());
- for (const auto& p : kSignalMethods) {
- power_manager_proxy_->ConnectToSignal(
- power_manager::kPowerManagerInterface, p.first,
- base::BindRepeating(p.second, weak_ptr_factory_.GetWeakPtr()),
- on_connected_callback);
- }
- RegisterSuspendDelays();
- RequestStatusUpdate();
- RequestThermalState();
- CheckAmbientColorSupport();
- }
- // PowerManagerClient overrides:
- void AddObserver(Observer* observer) override {
- DCHECK(observer); // http://crbug.com/119976
- observers_.AddObserver(observer);
- if (service_available_)
- observer->PowerManagerBecameAvailable(*service_available_);
- }
- void RemoveObserver(Observer* observer) override {
- observers_.RemoveObserver(observer);
- }
- bool HasObserver(const Observer* observer) const override {
- return observers_.HasObserver(observer);
- }
- void SetRenderProcessManagerDelegate(
- base::WeakPtr<RenderProcessManagerDelegate> delegate) override {
- DCHECK(!render_process_manager_delegate_)
- << "There can be only one! ...RenderProcessManagerDelegate";
- render_process_manager_delegate_ = delegate;
- }
- void DecreaseScreenBrightness(bool allow_off) override {
- dbus::MethodCall method_call(
- power_manager::kPowerManagerInterface,
- power_manager::kDecreaseScreenBrightnessMethod);
- dbus::MessageWriter writer(&method_call);
- writer.AppendBool(allow_off);
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- void IncreaseScreenBrightness() override {
- SimpleMethodCallToPowerManager(
- power_manager::kIncreaseScreenBrightnessMethod);
- }
- void DecreaseKeyboardBrightness() override {
- SimpleMethodCallToPowerManager(
- power_manager::kDecreaseKeyboardBrightnessMethod);
- }
- void IncreaseKeyboardBrightness() override {
- SimpleMethodCallToPowerManager(
- power_manager::kIncreaseKeyboardBrightnessMethod);
- }
- const absl::optional<power_manager::PowerSupplyProperties>& GetLastStatus()
- override {
- return proto_;
- }
- void SetScreenBrightness(
- const power_manager::SetBacklightBrightnessRequest& request) override {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kSetScreenBrightnessMethod);
- if (!dbus::MessageWriter(&method_call).AppendProtoAsArrayOfBytes(request)) {
- POWER_LOG(ERROR) << "Error serializing "
- << power_manager::kSetScreenBrightnessMethod
- << " request";
- return;
- }
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- void GetScreenBrightnessPercent(
- DBusMethodCallback<double> callback) override {
- dbus::MethodCall method_call(
- power_manager::kPowerManagerInterface,
- power_manager::kGetScreenBrightnessPercentMethod);
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(
- &PowerManagerClientImpl::OnGetScreenOrKeyboardBrightnessPercent,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
- }
- void GetKeyboardBrightnessPercent(
- DBusMethodCallback<double> callback) override {
- dbus::MethodCall method_call(
- power_manager::kPowerManagerInterface,
- power_manager::kGetKeyboardBrightnessPercentMethod);
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(
- &PowerManagerClientImpl::OnGetScreenOrKeyboardBrightnessPercent,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
- }
- void RequestStatusUpdate() override {
- POWER_LOG(USER) << "RequestStatusUpdate";
- dbus::MethodCall method_call(
- power_manager::kPowerManagerInterface,
- power_manager::kGetPowerSupplyPropertiesMethod);
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(
- &PowerManagerClientImpl::OnGetPowerSupplyPropertiesMethod,
- weak_ptr_factory_.GetWeakPtr()));
- }
- void RequestAllPeripheralBatteryUpdate() override {
- POWER_LOG(USER) << "RequestAllPeripheralBatteryUpdate";
- dbus::MethodCall method_call(
- power_manager::kPowerManagerInterface,
- power_manager::kRefreshAllPeripheralBatteryMethod);
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(
- &PowerManagerClientImpl::OnRefreshAllPeripheralBatteryMethod,
- weak_ptr_factory_.GetWeakPtr()));
- }
- void RequestThermalState() override {
- POWER_LOG(USER) << "RequestThermalState";
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kGetThermalStateMethod);
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(&PowerManagerClientImpl::OnGetCurrentThermalStateMethod,
- weak_ptr_factory_.GetWeakPtr()));
- }
- void RequestSuspend() override {
- POWER_LOG(USER) << "RequestSuspend";
- SimpleMethodCallToPowerManager(power_manager::kRequestSuspendMethod);
- }
- void RequestRestart(power_manager::RequestRestartReason reason,
- const std::string& description) override {
- POWER_LOG(USER) << "RequestRestart: " << reason << " (" << description
- << ")";
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kRequestRestartMethod);
- dbus::MessageWriter writer(&method_call);
- writer.AppendInt32(reason);
- writer.AppendString(description);
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- void RequestShutdown(power_manager::RequestShutdownReason reason,
- const std::string& description) override {
- POWER_LOG(USER) << "RequestShutdown: " << reason << " (" << description
- << ")";
- for (auto& observer : observers_)
- observer.ShutdownRequested(reason);
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kRequestShutdownMethod);
- dbus::MessageWriter writer(&method_call);
- writer.AppendInt32(reason);
- writer.AppendString(description);
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- void NotifyUserActivity(power_manager::UserActivityType type) override {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kHandleUserActivityMethod);
- dbus::MessageWriter writer(&method_call);
- writer.AppendInt32(type);
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- void NotifyVideoActivity(bool is_fullscreen) override {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kHandleVideoActivityMethod);
- dbus::MessageWriter writer(&method_call);
- writer.AppendBool(is_fullscreen);
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- void NotifyWakeNotification() override {
- SimpleMethodCallToPowerManager(
- power_manager::kHandleWakeNotificationMethod);
- }
- void SetPolicy(const power_manager::PowerManagementPolicy& policy) override {
- POWER_LOG(USER) << "SetPolicy";
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kSetPolicyMethod);
- dbus::MessageWriter writer(&method_call);
- if (!writer.AppendProtoAsArrayOfBytes(policy)) {
- POWER_LOG(ERROR) << "Error calling " << power_manager::kSetPolicyMethod;
- return;
- }
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- void SetIsProjecting(bool is_projecting) override {
- POWER_LOG(USER) << "SetIsProjecting";
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kSetIsProjectingMethod);
- dbus::MessageWriter writer(&method_call);
- writer.AppendBool(is_projecting);
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- last_is_projecting_ = is_projecting;
- }
- void SetPowerSource(const std::string& id) override {
- POWER_LOG(USER) << "SetPowerSource: " << id;
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kSetPowerSourceMethod);
- dbus::MessageWriter writer(&method_call);
- writer.AppendString(id);
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- void SetBacklightsForcedOff(bool forced_off) override {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kSetBacklightsForcedOffMethod);
- dbus::MessageWriter(&method_call).AppendBool(forced_off);
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- void GetBacklightsForcedOff(DBusMethodCallback<bool> callback) override {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kGetBacklightsForcedOffMethod);
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(&PowerManagerClientImpl::OnGetBacklightsForcedOff,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
- }
- void SetKeyboardBacklightToggledOff(bool toggled_off) override {
- dbus::MethodCall method_call(
- power_manager::kPowerManagerInterface,
- power_manager::kSetKeyboardBacklightToggledOffMethod);
- dbus::MessageWriter(&method_call).AppendBool(toggled_off);
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- void GetKeyboardBacklightToggledOff(
- DBusMethodCallback<bool> callback) override {
- dbus::MethodCall method_call(
- power_manager::kPowerManagerInterface,
- power_manager::kGetKeyboardBacklightToggledOffMethod);
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(
- &PowerManagerClientImpl::OnGetKeyboardBacklightToggledOff,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
- }
- void GetSwitchStates(DBusMethodCallback<SwitchStates> callback) override {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kGetSwitchStatesMethod);
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(&PowerManagerClientImpl::OnGetSwitchStates,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
- }
- void GetInactivityDelays(
- DBusMethodCallback<power_manager::PowerManagementPolicy::Delays> callback)
- override {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kGetInactivityDelaysMethod);
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(&PowerManagerClientImpl::OnGetInactivityDelays,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
- }
- void BlockSuspend(const base::UnguessableToken& token,
- const std::string& debug_info) override {
- DCHECK(OnOriginThread());
- DCHECK(suspend_is_pending_);
- DCHECK(token);
- suspend_readiness_registry_[token.ToString()] = {
- pending_suspend_id_, suspending_from_dark_resume_, debug_info};
- }
- void UnblockSuspend(const base::UnguessableToken& token) override {
- DCHECK(OnOriginThread());
- auto registration = suspend_readiness_registry_.find(token.ToString());
- if (registration == suspend_readiness_registry_.end() ||
- registration->second.suspend_id != pending_suspend_id_ ||
- registration->second.suspending_from_dark_resume !=
- suspending_from_dark_resume_ ||
- !suspend_is_pending_) {
- return;
- }
- suspend_readiness_registry_.erase(registration);
- MaybeReportSuspendReadiness();
- }
- bool SupportsAmbientColor() override {
- return device_supports_ambient_color_;
- }
- void CreateArcTimers(
- const std::string& tag,
- std::vector<std::pair<clockid_t, base::ScopedFD>> arc_timer_requests,
- DBusMethodCallback<std::vector<TimerId>> callback) override {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kCreateArcTimersMethod);
- // Write mojo arguments i.e. client's tag and array of {int, fd} as a D-Bus
- // message.
- dbus::MessageWriter writer(&method_call);
- writer.AppendString(tag);
- dbus::MessageWriter array_writer(nullptr);
- writer.OpenArray("(ih)", &array_writer);
- for (const auto& request : arc_timer_requests) {
- dbus::MessageWriter struct_writer(nullptr);
- array_writer.OpenStruct(&struct_writer);
- struct_writer.AppendInt32(static_cast<int32_t>(request.first));
- // This dups the file descriptor and the original one stored as
- // base::ScopedFD in |arc_timer_requests| will be closed when the function
- // ends and it goes out of scope.
- struct_writer.AppendFileDescriptor(request.second.get());
- array_writer.CloseContainer(&struct_writer);
- }
- writer.CloseContainer(&array_writer);
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(&OnCreateArcTimersDBusMethod, std::move(callback)));
- }
- void StartArcTimer(TimerId timer_id,
- base::TimeTicks absolute_expiration_time,
- VoidDBusMethodCallback callback) override {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kStartArcTimerMethod);
- // Write clock id and 64-bit expiration time ticks value as a D-Bus message.
- dbus::MessageWriter writer(&method_call);
- writer.AppendInt32(timer_id);
- // The absolute ticks are still being sent because base::TimeTicks() returns
- // 0.
- writer.AppendInt64(
- (absolute_expiration_time - base::TimeTicks()).InMicroseconds());
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(&OnVoidDBusMethod, std::move(callback)));
- }
- void DeleteArcTimers(const std::string& tag,
- VoidDBusMethodCallback callback) override {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kDeleteArcTimersMethod);
- dbus::MessageWriter writer(&method_call);
- writer.AppendString(tag);
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(&OnVoidDBusMethod, std::move(callback)));
- }
- base::TimeDelta GetDarkSuspendDelayTimeout() override {
- return max_dark_suspend_delay_timeout_;
- }
- void RefreshBluetoothBattery(const std::string& address) override {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kRefreshBluetoothBatteryMethod);
- dbus::MessageWriter writer(&method_call);
- writer.AppendString(address);
- // This refresh request is best effort, so we don't have to handle errors.
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- void SetExternalDisplayALSBrightness(bool enabled) override {
- dbus::MethodCall method_call(
- power_manager::kPowerManagerInterface,
- power_manager::kSetExternalDisplayALSBrightnessMethod);
- dbus::MessageWriter writer(&method_call);
- writer.AppendBool(enabled);
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- void GetExternalDisplayALSBrightness(
- DBusMethodCallback<bool> callback) override {
- dbus::MethodCall method_call(
- power_manager::kPowerManagerInterface,
- power_manager::kGetExternalDisplayALSBrightnessMethod);
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(
- &PowerManagerClientImpl::OnGetExternalDisplayALSBrightness,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
- }
- void ChargeNowForAdaptiveCharging() override {
- dbus::MethodCall method_call(
- power_manager::kPowerManagerInterface,
- power_manager::kChargeNowForAdaptiveChargingMethod);
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- private:
- // Returns true if the current thread is the origin thread.
- bool OnOriginThread() {
- return base::PlatformThread::CurrentId() == origin_thread_id_;
- }
- // Called when a dbus signal is initially connected.
- void SignalConnected(const std::string& interface_name,
- const std::string& signal_name,
- bool success) {
- if (!success)
- POWER_LOG(ERROR) << "Failed to connect to signal " << signal_name << ".";
- }
- // Makes a method call to power manager with no arguments and no response.
- void SimpleMethodCallToPowerManager(const std::string& method_name) {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- method_name);
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- void NotifyServiceBecameAvailable(bool available) {
- service_available_ = available;
- for (auto& observer : observers_)
- observer.PowerManagerBecameAvailable(available);
- }
- void NameOwnerChangedReceived(const std::string& old_owner,
- const std::string& new_owner) {
- POWER_LOG(EVENT) << "Power manager restarted. Old owner: "
- << (old_owner.empty() ? "[none]" : old_owner.c_str())
- << " New owner: "
- << (new_owner.empty() ? "[none]" : new_owner.c_str());
- suspend_is_pending_ = false;
- pending_suspend_id_ = -1;
- suspending_from_dark_resume_ = false;
- if (!new_owner.empty()) {
- POWER_LOG(EVENT) << "Sending initial state to power manager";
- RegisterSuspendDelays();
- SetIsProjecting(last_is_projecting_);
- for (auto& observer : observers_)
- observer.PowerManagerRestarted();
- }
- }
- void NotifyInitialization() {
- for (auto& observer : observers_)
- observer.PowerManagerInitialized();
- }
- void ScreenBrightnessChangedReceived(dbus::Signal* signal) {
- dbus::MessageReader reader(signal);
- power_manager::BacklightBrightnessChange proto;
- if (!reader.PopArrayOfBytesAsProto(&proto)) {
- POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
- << power_manager::kScreenBrightnessChangedSignal
- << " signal";
- return;
- }
- POWER_LOG(DEBUG) << "Screen brightness changed to " << proto.percent()
- << ": cause " << proto.cause();
- for (auto& observer : observers_)
- observer.ScreenBrightnessChanged(proto);
- }
- void AmbientColorTemperatureChangedReceived(dbus::Signal* signal) {
- dbus::MessageReader reader(signal);
- int32_t color_temperature = 0;
- if (!reader.PopInt32(&color_temperature)) {
- POWER_LOG(ERROR) << "Unable to decode read ambient color from "
- << power_manager::kAmbientColorTemperatureChangedSignal
- << " signal";
- return;
- }
- for (auto& observer : observers_)
- observer.AmbientColorChanged(color_temperature);
- }
- void KeyboardBrightnessChangedReceived(dbus::Signal* signal) {
- dbus::MessageReader reader(signal);
- power_manager::BacklightBrightnessChange proto;
- if (!reader.PopArrayOfBytesAsProto(&proto)) {
- POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
- << power_manager::kKeyboardBrightnessChangedSignal
- << " signal";
- return;
- }
- POWER_LOG(DEBUG) << "Keyboard brightness changed to " << proto.percent()
- << ": cause " << proto.cause();
- for (auto& observer : observers_)
- observer.KeyboardBrightnessChanged(proto);
- }
- void ScreenIdleStateChangedReceived(dbus::Signal* signal) {
- dbus::MessageReader reader(signal);
- power_manager::ScreenIdleState proto;
- if (!reader.PopArrayOfBytesAsProto(&proto)) {
- POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
- << power_manager::kScreenIdleStateChangedSignal
- << " signal";
- return;
- }
- for (auto& observer : observers_)
- observer.ScreenIdleStateChanged(proto);
- }
- void InactivityDelaysChangedReceived(dbus::Signal* signal) {
- dbus::MessageReader reader(signal);
- power_manager::PowerManagementPolicy::Delays proto;
- if (!reader.PopArrayOfBytesAsProto(&proto)) {
- POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
- << power_manager::kInactivityDelaysChangedSignal
- << " signal";
- return;
- }
- for (auto& observer : observers_)
- observer.InactivityDelaysChanged(proto);
- }
- void PeripheralBatteryStatusReceived(dbus::Signal* signal) {
- dbus::MessageReader reader(signal);
- power_manager::PeripheralBatteryStatus protobuf_status;
- if (!reader.PopArrayOfBytesAsProto(&protobuf_status)) {
- POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
- << power_manager::kPeripheralBatteryStatusSignal
- << " signal";
- return;
- }
- std::string path = protobuf_status.path();
- std::string name = protobuf_status.name();
- int level = protobuf_status.has_level() ? protobuf_status.level() : -1;
- power_manager::PeripheralBatteryStatus_ChargeStatus status =
- protobuf_status.has_charge_status()
- ? protobuf_status.charge_status()
- : power_manager::
- PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_UNKNOWN;
- bool active_update = protobuf_status.has_active_update()
- ? protobuf_status.active_update()
- : false;
- std::string serial_number = "";
- if (protobuf_status.has_serial_number())
- serial_number = protobuf_status.serial_number();
- for (auto& observer : observers_)
- observer.PeripheralBatteryStatusReceived(path, name, level, status,
- serial_number, active_update);
- }
- void PowerSupplyPollReceived(dbus::Signal* signal) {
- POWER_LOG(DEBUG) << "Received power supply poll signal.";
- dbus::MessageReader reader(signal);
- power_manager::PowerSupplyProperties protobuf;
- if (reader.PopArrayOfBytesAsProto(&protobuf)) {
- HandlePowerSupplyProperties(protobuf);
- } else {
- POWER_LOG(ERROR) << "Unable to decode "
- << power_manager::kPowerSupplyPollSignal << " signal";
- }
- }
- void OnGetCurrentThermalStateMethod(dbus::Response* response) {
- if (!response) {
- POWER_LOG(ERROR) << "Error calling "
- << power_manager::kGetThermalStateMethod;
- return;
- }
- dbus::MessageReader reader(response);
- power_manager::ThermalEvent protobuf;
- if (!reader.PopArrayOfBytesAsProto(&protobuf)) {
- POWER_LOG(ERROR) << "Unable to decode "
- << power_manager::kGetThermalStateMethod << " response";
- return;
- }
- POWER_LOG(USER) << "Got " << power_manager::kGetThermalStateMethod
- << " response:"
- << " thermal_state=" << protobuf.thermal_state()
- << " timestamp=" << protobuf.timestamp();
- base::PowerMonitorDeviceSource::ThermalEventReceived(
- GetThermalStateFromProtoEnum(protobuf.thermal_state()));
- }
- void OnGetPowerSupplyPropertiesMethod(dbus::Response* response) {
- // This is the last callback to run after all the initialization in |Init|.
- // Notify all observers that the initialization is complete.
- base::ScopedClosureRunner notify_runner(base::BindOnce(
- &PowerManagerClientImpl::NotifyInitialization, base::Unretained(this)));
- if (!response) {
- POWER_LOG(ERROR) << "Error calling "
- << power_manager::kGetPowerSupplyPropertiesMethod;
- return;
- }
- dbus::MessageReader reader(response);
- power_manager::PowerSupplyProperties protobuf;
- if (reader.PopArrayOfBytesAsProto(&protobuf)) {
- HandlePowerSupplyProperties(protobuf);
- } else {
- POWER_LOG(ERROR) << "Unable to decode "
- << power_manager::kGetPowerSupplyPropertiesMethod
- << " response";
- }
- }
- void OnRefreshAllPeripheralBatteryMethod(dbus::Response* response) {
- if (!response) {
- POWER_LOG(ERROR) << "Error calling "
- << power_manager::kRefreshAllPeripheralBatteryMethod;
- return;
- }
- }
- void OnGetScreenOrKeyboardBrightnessPercent(
- DBusMethodCallback<double> callback,
- dbus::Response* response) {
- if (!response) {
- std::move(callback).Run(absl::nullopt);
- return;
- }
- dbus::MessageReader reader(response);
- double percent = 0.0;
- if (!reader.PopDouble(&percent)) {
- POWER_LOG(ERROR) << "Error reading response from powerd: "
- << response->ToString();
- std::move(callback).Run(absl::nullopt);
- return;
- }
- std::move(callback).Run(percent);
- }
- void OnGetBacklightsForcedOff(DBusMethodCallback<bool> callback,
- dbus::Response* response) {
- if (!response) {
- POWER_LOG(ERROR) << "Error calling "
- << power_manager::kGetBacklightsForcedOffMethod;
- std::move(callback).Run(absl::nullopt);
- return;
- }
- dbus::MessageReader reader(response);
- bool state = false;
- if (!reader.PopBool(&state)) {
- POWER_LOG(ERROR) << "Error reading response from powerd: "
- << response->ToString();
- std::move(callback).Run(absl::nullopt);
- return;
- }
- std::move(callback).Run(state);
- }
- void OnGetKeyboardBacklightToggledOff(DBusMethodCallback<bool> callback,
- dbus::Response* response) {
- if (!response) {
- POWER_LOG(ERROR) << "Error calling "
- << power_manager::kGetKeyboardBacklightToggledOffMethod;
- std::move(callback).Run(absl::nullopt);
- return;
- }
- dbus::MessageReader reader(response);
- bool toggled_off = false;
- if (!reader.PopBool(&toggled_off)) {
- POWER_LOG(ERROR) << "Error reading response from powerd: "
- << response->ToString();
- std::move(callback).Run(absl::nullopt);
- return;
- }
- std::move(callback).Run(toggled_off);
- }
- void CheckAmbientColorSupport() {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- power_manager::kHasAmbientColorDeviceMethod);
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::BindOnce(&PowerManagerClientImpl::OnHasAmbientColorDevice,
- weak_ptr_factory_.GetWeakPtr()));
- }
- void OnHasAmbientColorDevice(dbus::Response* response) {
- if (!response) {
- device_supports_ambient_color_ = false;
- return;
- }
- dbus::MessageReader reader(response);
- bool is_supported = false;
- if (!reader.PopBool(&is_supported)) {
- POWER_LOG(ERROR) << "Error reading response from powerd: "
- << response->ToString();
- device_supports_ambient_color_ = false;
- return;
- }
- device_supports_ambient_color_ = is_supported;
- }
- void OnGetSwitchStates(DBusMethodCallback<SwitchStates> callback,
- dbus::Response* response) {
- if (!response) {
- POWER_LOG(ERROR) << "Error calling "
- << power_manager::kGetSwitchStatesMethod;
- std::move(callback).Run(absl::nullopt);
- return;
- }
- dbus::MessageReader reader(response);
- power_manager::SwitchStates proto;
- if (!reader.PopArrayOfBytesAsProto(&proto)) {
- POWER_LOG(ERROR) << "Error parsing response from "
- << power_manager::kGetSwitchStatesMethod;
- std::move(callback).Run(absl::nullopt);
- return;
- }
- std::move(callback).Run(
- SwitchStates{GetLidStateFromProtoEnum(proto.lid_state()),
- GetTabletModeFromProtoEnum(proto.tablet_mode())});
- }
- void OnGetInactivityDelays(
- DBusMethodCallback<power_manager::PowerManagementPolicy::Delays> callback,
- dbus::Response* response) {
- if (!response) {
- POWER_LOG(ERROR) << "Error calling "
- << power_manager::kGetInactivityDelaysMethod;
- std::move(callback).Run(absl::nullopt);
- return;
- }
- dbus::MessageReader reader(response);
- power_manager::PowerManagementPolicy::Delays proto;
- if (!reader.PopArrayOfBytesAsProto(&proto)) {
- POWER_LOG(ERROR) << "Error parsing response from "
- << power_manager::kGetInactivityDelaysMethod;
- std::move(callback).Run(absl::nullopt);
- return;
- }
- std::move(callback).Run(proto);
- }
- void OnGetExternalDisplayALSBrightness(DBusMethodCallback<bool> callback,
- dbus::Response* response) {
- if (!response) {
- POWER_LOG(ERROR) << "Error calling "
- << power_manager::kGetExternalDisplayALSBrightnessMethod;
- std::move(callback).Run(false);
- return;
- }
- dbus::MessageReader reader(response);
- bool enabled = false;
- if (!reader.PopBool(&enabled)) {
- POWER_LOG(ERROR) << "Error parsing response from "
- << power_manager::kGetExternalDisplayALSBrightnessMethod;
- std::move(callback).Run(false);
- return;
- }
- std::move(callback).Run(enabled);
- }
- void HandlePowerSupplyProperties(
- const power_manager::PowerSupplyProperties& proto) {
- proto_ = SanitizePowerSupplyProperties(proto);
- for (auto& observer : observers_)
- observer.PowerChanged(*proto_);
- const bool on_battery =
- proto_->external_power() ==
- power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED;
- base::PowerMonitorDeviceSource::SetPowerSource(on_battery);
- }
- void HandleRegisterSuspendDelayReply(bool dark_suspend,
- const std::string& method_name,
- dbus::Response* response) {
- if (!response) {
- POWER_LOG(ERROR) << "Error calling " << method_name;
- return;
- }
- dbus::MessageReader reader(response);
- power_manager::RegisterSuspendDelayReply protobuf;
- if (!reader.PopArrayOfBytesAsProto(&protobuf)) {
- POWER_LOG(ERROR) << "Unable to parse reply from " << method_name;
- return;
- }
- if (dark_suspend) {
- dark_suspend_delay_id_ = protobuf.delay_id();
- has_dark_suspend_delay_id_ = true;
- // Set |max_dark_suspend_delay_timeout_| to the minimum time power manager
- // guarantees before resuspending.
- max_dark_suspend_delay_timeout_ =
- base::Milliseconds(protobuf.min_delay_timeout_ms());
- POWER_LOG(EVENT) << "Registered dark suspend delay "
- << dark_suspend_delay_id_;
- } else {
- suspend_delay_id_ = protobuf.delay_id();
- has_suspend_delay_id_ = true;
- POWER_LOG(EVENT) << "Registered suspend delay " << suspend_delay_id_;
- }
- }
- void SuspendImminentReceived(dbus::Signal* signal) {
- HandleSuspendImminent(false /* in_dark_resume */, signal);
- }
- void DarkSuspendImminentReceived(dbus::Signal* signal) {
- HandleSuspendImminent(true /* in_dark_resume */, signal);
- }
- void HandleSuspendImminent(bool in_dark_resume, dbus::Signal* signal) {
- std::string signal_name = signal->GetMember();
- if ((in_dark_resume && !has_dark_suspend_delay_id_) ||
- (!in_dark_resume && !has_suspend_delay_id_)) {
- POWER_LOG(ERROR) << "Received unrequested " << signal_name << " signal";
- return;
- }
- dbus::MessageReader reader(signal);
- power_manager::SuspendImminent proto;
- if (!reader.PopArrayOfBytesAsProto(&proto)) {
- POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
- << signal_name << " signal";
- return;
- }
- POWER_LOG(EVENT) << "Got " << signal_name
- << " signal announcing suspend attempt "
- << proto.suspend_id();
- // If a previous suspend is pending from the same state we are currently in
- // (fully powered on or in dark resume), then something's gone a little
- // wonky.
- if (suspend_is_pending_ && suspending_from_dark_resume_ == in_dark_resume) {
- POWER_LOG(ERROR) << "Got " << signal_name
- << " signal about pending suspend attempt "
- << proto.suspend_id()
- << " while still waiting on attempt "
- << pending_suspend_id_;
- }
- pending_suspend_id_ = proto.suspend_id();
- suspend_is_pending_ = true;
- suspending_from_dark_resume_ = in_dark_resume;
- suspend_readiness_registry_.clear();
- // Record the fact that observers are being notified to ensure that we don't
- // report readiness prematurely if one of them calls BlockSuspend() and then
- // runs UnblockSuspend() synchonously instead of asynchronously.
- notifying_observers_about_suspend_imminent_ = true;
- if (suspending_from_dark_resume_) {
- for (auto& observer : observers_)
- observer.DarkSuspendImminent();
- } else {
- for (auto& observer : observers_)
- observer.SuspendImminent(proto.reason());
- }
- notifying_observers_about_suspend_imminent_ = false;
- base::PowerMonitorDeviceSource::HandleSystemSuspending();
- MaybeReportSuspendReadiness();
- }
- void SuspendDoneReceived(dbus::Signal* signal) {
- dbus::MessageReader reader(signal);
- power_manager::SuspendDone proto;
- if (!reader.PopArrayOfBytesAsProto(&proto)) {
- POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
- << power_manager::kSuspendDoneSignal << " signal";
- return;
- }
- const base::TimeDelta duration =
- base::TimeDelta::FromInternalValue(proto.suspend_duration());
- POWER_LOG(EVENT) << "Got " << power_manager::kSuspendDoneSignal
- << " signal:"
- << " suspend_id=" << proto.suspend_id()
- << " duration=" << duration.InSeconds() << " sec"
- << " deepest_state=" << proto.deepest_state();
- // RenderProcessManagerDelegate is only notified that suspend is imminent
- // when readiness is being reported to powerd. If the suspend attempt was
- // cancelled before then, we shouldn't notify the delegate about completion.
- const bool cancelled_while_regular_suspend_pending =
- suspend_is_pending_ && !suspending_from_dark_resume_;
- if (render_process_manager_delegate_ &&
- !cancelled_while_regular_suspend_pending)
- render_process_manager_delegate_->SuspendDone();
- // powerd always pairs each SuspendImminent signal with SuspendDone before
- // starting the next suspend attempt, so we should no longer report
- // readiness for any in-progress suspend attempts.
- pending_suspend_id_ = -1;
- suspend_is_pending_ = false;
- suspending_from_dark_resume_ = false;
- // powerd gives clients a limited amount of time to report suspend
- // readiness. Log the stragglers within Chrome to aid in debugging.
- for (const auto& it : suspend_readiness_registry_) {
- LOG(WARNING) << "Didn't report suspend readiness due to "
- << it.second.debug_info;
- }
- suspend_readiness_registry_.clear();
- for (auto& observer : observers_)
- observer.SuspendDoneEx(proto);
- base::PowerMonitorDeviceSource::HandleSystemResumed();
- }
- void IdleActionImminentReceived(dbus::Signal* signal) {
- dbus::MessageReader reader(signal);
- power_manager::IdleActionImminent proto;
- if (!reader.PopArrayOfBytesAsProto(&proto)) {
- POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
- << power_manager::kIdleActionImminentSignal << " signal";
- return;
- }
- for (auto& observer : observers_) {
- observer.IdleActionImminent(
- base::TimeDelta::FromInternalValue(proto.time_until_idle_action()));
- }
- }
- void IdleActionDeferredReceived(dbus::Signal* signal) {
- for (auto& observer : observers_)
- observer.IdleActionDeferred();
- }
- void InputEventReceived(dbus::Signal* signal) {
- dbus::MessageReader reader(signal);
- power_manager::InputEvent proto;
- if (!reader.PopArrayOfBytesAsProto(&proto)) {
- POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
- << power_manager::kInputEventSignal << " signal";
- return;
- }
- base::TimeTicks timestamp =
- base::TimeTicks::FromInternalValue(proto.timestamp());
- POWER_LOG(USER) << "Got " << power_manager::kInputEventSignal << " signal:"
- << " type=" << proto.type()
- << " timestamp=" << proto.timestamp();
- switch (proto.type()) {
- case power_manager::InputEvent_Type_POWER_BUTTON_DOWN:
- case power_manager::InputEvent_Type_POWER_BUTTON_UP: {
- const bool down =
- (proto.type() == power_manager::InputEvent_Type_POWER_BUTTON_DOWN);
- for (auto& observer : observers_)
- observer.PowerButtonEventReceived(down, timestamp);
- // Tell powerd that Chrome has handled power button presses.
- if (down) {
- dbus::MethodCall method_call(
- power_manager::kPowerManagerInterface,
- power_manager::kHandlePowerButtonAcknowledgmentMethod);
- dbus::MessageWriter writer(&method_call);
- writer.AppendInt64(proto.timestamp());
- power_manager_proxy_->CallMethod(
- &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- break;
- }
- case power_manager::InputEvent_Type_LID_OPEN:
- for (auto& observer : observers_)
- observer.LidEventReceived(LidState::OPEN, timestamp);
- break;
- case power_manager::InputEvent_Type_LID_CLOSED:
- for (auto& observer : observers_)
- observer.LidEventReceived(LidState::CLOSED, timestamp);
- break;
- case power_manager::InputEvent_Type_TABLET_MODE_ON:
- for (auto& observer : observers_)
- observer.TabletModeEventReceived(TabletMode::ON, timestamp);
- break;
- case power_manager::InputEvent_Type_TABLET_MODE_OFF:
- for (auto& observer : observers_)
- observer.TabletModeEventReceived(TabletMode::OFF, timestamp);
- break;
- default:
- // TODO(henryhsu): handle the missing cases.
- break;
- }
- }
- void ThermalEventReceived(dbus::Signal* signal) {
- dbus::MessageReader reader(signal);
- power_manager::ThermalEvent proto;
- if (!reader.PopArrayOfBytesAsProto(&proto)) {
- POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
- << power_manager::kThermalEventSignal << " signal";
- return;
- }
- POWER_LOG(USER) << "Got " << power_manager::kThermalEventSignal
- << " signal:"
- << " thermal_state=" << proto.thermal_state()
- << " timestamp=" << proto.timestamp();
- base::PowerMonitorDeviceSource::ThermalEventReceived(
- GetThermalStateFromProtoEnum(proto.thermal_state()));
- }
- void RegisterSuspendDelayImpl(
- const std::string& method_name,
- const power_manager::RegisterSuspendDelayRequest& protobuf_request,
- dbus::ObjectProxy::ResponseCallback callback) {
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- method_name);
- dbus::MessageWriter writer(&method_call);
- if (!writer.AppendProtoAsArrayOfBytes(protobuf_request)) {
- POWER_LOG(ERROR) << "Error constructing message for " << method_name;
- return;
- }
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- std::move(callback));
- }
- // Registers suspend delays with the power manager. This is usually only
- // called at startup, but if the power manager restarts, we need to create new
- // delays.
- void RegisterSuspendDelays() {
- // Throw out any old delay that was registered.
- suspend_delay_id_ = -1;
- has_suspend_delay_id_ = false;
- dark_suspend_delay_id_ = -1;
- has_dark_suspend_delay_id_ = false;
- power_manager::RegisterSuspendDelayRequest protobuf_request;
- base::TimeDelta timeout = base::Milliseconds(kSuspendDelayTimeoutMs);
- protobuf_request.set_timeout(timeout.ToInternalValue());
- protobuf_request.set_description(kSuspendDelayDescription);
- RegisterSuspendDelayImpl(
- power_manager::kRegisterSuspendDelayMethod, protobuf_request,
- base::BindOnce(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply,
- weak_ptr_factory_.GetWeakPtr(), false,
- power_manager::kRegisterSuspendDelayMethod));
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- chromeos::switches::kRegisterMaxDarkSuspendDelay)) {
- // Negative timeout means request maximum delay.
- protobuf_request.set_timeout(-1);
- }
- RegisterSuspendDelayImpl(
- power_manager::kRegisterDarkSuspendDelayMethod, protobuf_request,
- base::BindOnce(&PowerManagerClientImpl::HandleRegisterSuspendDelayReply,
- weak_ptr_factory_.GetWeakPtr(), true,
- power_manager::kRegisterDarkSuspendDelayMethod));
- }
- // Reports suspend readiness to powerd if no observers are still holding
- // suspend readiness callbacks.
- void MaybeReportSuspendReadiness() {
- DCHECK(suspend_is_pending_);
- // Avoid reporting suspend readiness if some observers have yet to be
- // notified about the pending attempt.
- if (notifying_observers_about_suspend_imminent_)
- return;
- if (!suspend_readiness_registry_.empty())
- return;
- std::string method_name;
- int32_t delay_id = -1;
- if (suspending_from_dark_resume_) {
- method_name = power_manager::kHandleDarkSuspendReadinessMethod;
- delay_id = dark_suspend_delay_id_;
- } else {
- method_name = power_manager::kHandleSuspendReadinessMethod;
- delay_id = suspend_delay_id_;
- }
- if (render_process_manager_delegate_ && !suspending_from_dark_resume_)
- render_process_manager_delegate_->SuspendImminent();
- dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
- method_name);
- dbus::MessageWriter writer(&method_call);
- POWER_LOG(EVENT) << "Announcing readiness of suspend delay " << delay_id
- << " for suspend attempt " << pending_suspend_id_;
- power_manager::SuspendReadinessInfo protobuf_request;
- protobuf_request.set_delay_id(delay_id);
- protobuf_request.set_suspend_id(pending_suspend_id_);
- pending_suspend_id_ = -1;
- suspend_is_pending_ = false;
- if (!writer.AppendProtoAsArrayOfBytes(protobuf_request)) {
- POWER_LOG(ERROR) << "Error constructing message for " << method_name;
- return;
- }
- power_manager_proxy_->CallMethod(&method_call,
- dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::DoNothing());
- }
- // Origin thread (i.e. the UI thread in production).
- base::PlatformThreadId origin_thread_id_;
- dbus::ObjectProxy* power_manager_proxy_ = nullptr;
- base::ObserverList<Observer>::Unchecked observers_;
- absl::optional<bool> service_available_;
- // The delay ID obtained from the RegisterSuspendDelay request.
- int32_t suspend_delay_id_ = -1;
- bool has_suspend_delay_id_ = false;
- // The delay ID obtained from the RegisterDarkSuspendDelay request.
- int32_t dark_suspend_delay_id_ = -1;
- bool has_dark_suspend_delay_id_ = false;
- // The maximum time power manager will wait before resuspending from a dark
- // resume.
- base::TimeDelta max_dark_suspend_delay_timeout_;
- // powerd-supplied ID corresponding to an imminent (either regular or dark)
- // suspend attempt that is currently being delayed.
- int32_t pending_suspend_id_ = -1;
- bool suspend_is_pending_ = false;
- // Set to true when the suspend currently being delayed was triggered during a
- // dark resume. Since |pending_suspend_id_| and |suspend_is_pending_| are
- // both shared by normal and dark suspends, |suspending_from_dark_resume_|
- // helps distinguish the context within which these variables are being used.
- bool suspending_from_dark_resume_ = false;
- struct SuspendInfo {
- int32_t suspend_id;
- bool suspending_from_dark_resume;
- std::string debug_info;
- };
- // A map that holds BlockSuspend() registrations. It maps from the token (in
- // string form) to details about the suspend.
- std::unordered_map<std::string, SuspendInfo> suspend_readiness_registry_;
- // Inspected by MaybeReportSuspendReadiness() to avoid prematurely notifying
- // powerd about suspend readiness while |observers_|' SuspendImminent()
- // methods are being called by HandleSuspendImminent().
- bool notifying_observers_about_suspend_imminent_ = false;
- // Last state passed to SetIsProjecting().
- bool last_is_projecting_ = false;
- // Whether the device supports ambient color. This value is checked when the
- // DBUS service starts and is cached.
- bool device_supports_ambient_color_ = false;
- // The last proto received from D-Bus; initially empty.
- absl::optional<power_manager::PowerSupplyProperties> proto_;
- // The delegate used to manage the power consumption of Chrome's renderer
- // processes.
- base::WeakPtr<RenderProcessManagerDelegate> render_process_manager_delegate_;
- // Note: This should remain the last member so it'll be destroyed and
- // invalidate its weak pointers before any other members are destroyed.
- base::WeakPtrFactory<PowerManagerClientImpl> weak_ptr_factory_{this};
- };
- PowerManagerClient::PowerManagerClient() {
- DCHECK(!g_instance);
- g_instance = this;
- }
- PowerManagerClient::~PowerManagerClient() {
- DCHECK_EQ(g_instance, this);
- g_instance = nullptr;
- }
- // static
- void PowerManagerClient::Initialize(dbus::Bus* bus) {
- DCHECK(bus);
- DCHECK(!g_instance);
- auto* power_manager_client = new PowerManagerClientImpl();
- power_manager_client->Init(bus);
- g_instance = power_manager_client;
- }
- // static
- void PowerManagerClient::InitializeFake() {
- new FakePowerManagerClient();
- }
- // static
- void PowerManagerClient::Shutdown() {
- delete g_instance;
- }
- // static
- PowerManagerClient* PowerManagerClient::Get() {
- return g_instance;
- }
- void PowerManagerClient::Observer::SuspendDoneEx(
- const power_manager::SuspendDone& proto) {
- const base::TimeDelta duration =
- base::TimeDelta::FromInternalValue(proto.suspend_duration());
- this->SuspendDone(duration);
- }
- } // namespace chromeos
|