blob: c6d88224e393452605fc344604ace0a174956d29 [file] [log] [blame]
// Copyright 2019 The Chromium OS 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 "diagnostics/common/battery_utils.h"
#include <memory>
#include <utility>
#include <vector>
#include <chromeos/dbus/service_constants.h>
#include <dbus/bus.h>
#include <dbus/message.h>
#include <dbus/object_proxy.h>
#include "power_manager/proto_bindings/power_supply_properties.pb.h"
namespace diagnostics {
using BatteryInfoPtr = ::chromeos::cros_healthd::mojom::BatteryInfoPtr;
using BatteryInfo = ::chromeos::cros_healthd::mojom::BatteryInfo;
// Extract the battery metrics from the PowerSupplyProperties protobuf.
// Return true if the metrics could be successfully extracted from |response|
// and put into |output_info|.
bool ExtractBatteryMetrics(dbus::Response* response,
BatteryInfoPtr* output_info) {
DCHECK(response);
DCHECK(output_info);
BatteryInfo info;
power_manager::PowerSupplyProperties power_supply_proto;
dbus::MessageReader reader_response(response);
if (!reader_response.PopArrayOfBytesAsProto(&power_supply_proto)) {
LOG(ERROR) << "Could not successfully read power supply protobuf";
return false;
}
if (power_supply_proto.has_battery_cycle_count()) {
info.cycle_count = power_supply_proto.battery_cycle_count();
}
if (power_supply_proto.has_battery_vendor()) {
info.vendor = power_supply_proto.battery_vendor();
}
if (power_supply_proto.has_battery_voltage()) {
info.voltage_now = power_supply_proto.battery_voltage();
}
if (power_supply_proto.has_battery_charge_full()) {
info.charge_full = power_supply_proto.battery_charge_full();
}
if (power_supply_proto.has_battery_charge_full_design()) {
info.charge_full_design = power_supply_proto.battery_charge_full_design();
}
if (power_supply_proto.has_battery_serial_number()) {
info.serial_number = power_supply_proto.battery_serial_number();
}
if (power_supply_proto.has_battery_voltage_min_design()) {
info.voltage_min_design = power_supply_proto.battery_voltage_min_design();
}
*output_info = info.Clone();
return true;
}
namespace {
// Make a D-bus call to get the PowerSupplyProperties proto, which contains the
// battery metrics.
bool FetchBatteryMetrics(BatteryInfoPtr* output_info) {
dbus::Bus::Options options;
scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
if (!bus->Connect()) {
LOG(ERROR) << "Failed to connect to the system bus";
return false;
}
dbus::ObjectProxy* bus_proxy = bus->GetObjectProxy(
power_manager::kPowerManagerServiceName,
dbus::ObjectPath(power_manager::kPowerManagerServicePath));
constexpr base::TimeDelta kPowerManagerDBusTimeout =
base::TimeDelta::FromSeconds(3);
dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
power_manager::kGetPowerSupplyPropertiesMethod);
auto response = bus_proxy->CallMethodAndBlock(
&method_call, kPowerManagerDBusTimeout.InMilliseconds());
return ExtractBatteryMetrics(response.get(), output_info);
}
} // namespace
std::vector<BatteryInfoPtr> FetchBatteryInfo() {
// Since Chromebooks currently only support a single battery (main battery),
// the vector should have a size of one. In the future, if Chromebooks
// contain more batteries, they can easily be supported by the vector.
std::vector<BatteryInfoPtr> batteries{};
BatteryInfoPtr info;
if (FetchBatteryMetrics(&info)) {
batteries.push_back(std::move(info));
}
return batteries;
}
} // namespace diagnostics