blob: e73430e860c35ffec52a4f4958f1d993cfd9de52 [file] [log] [blame]
// Copyright (c) 2012 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 <iomanip>
#include <iostream> // NOLINT(readability/streams)
#include <memory>
#include <string>
#include <base/at_exit.h>
#include <base/command_line.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/macros.h>
#include <base/message_loop/message_pump_type.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/task/single_thread_task_executor.h>
#include <base/time/time.h>
#include <brillo/flag_helper.h>
#include "power_manager/common/battery_percentage_converter.h"
#include "power_manager/common/power_constants.h"
#include "power_manager/common/prefs.h"
#include "power_manager/powerd/system/dbus_wrapper_stub.h"
#include "power_manager/powerd/system/power_supply.h"
#include "power_manager/powerd/system/udev_stub.h"
// Displays info about battery and line power.
using base::TimeDelta;
using power_manager::system::PowerStatus;
namespace {
// Number of columns that should be used to display field names.
const int kFieldNameColumns = 27;
std::string BoolToString(bool value) {
return value ? "yes" : "no";
}
template <class T>
std::string ValueToString(T value) {
std::stringstream stream;
stream << value;
return stream.str();
}
class InfoDisplay {
public:
InfoDisplay() : name_indent_(0), value_indent_(0) {}
InfoDisplay(const InfoDisplay&) = delete;
InfoDisplay& operator=(const InfoDisplay&) = delete;
void SetIndent(int name_indent, int value_indent) {
name_indent_ = name_indent;
value_indent_ = value_indent;
}
void PrintStringValue(const std::string& name_field,
const std::string& value_field) {
std::cout << std::setw(name_indent_) << ""
<< std::setw(value_indent_ - name_indent_)
<< std::setiosflags(std::ios::left)
<< std::resetiosflags(std::ios::right) << name_field + ":"
<< value_field << std::endl;
}
template <class T>
void PrintValue(const std::string& name_field, T value) {
PrintStringValue(name_field, ValueToString(value));
}
void PrintString(const std::string& string) {
std::cout << std::setw(name_indent_) << "" << string << std::endl;
}
private:
int name_indent_;
int value_indent_;
};
} // namespace
int main(int argc, char** argv) {
brillo::FlagHelper::Init(
argc, argv,
"Print information obtained from /sys about the power supply.");
base::AtExitManager at_exit_manager;
base::SingleThreadTaskExecutor task_executor(base::MessagePumpType::IO);
logging::SetMinLogLevel(logging::LOGGING_WARNING);
power_manager::Prefs prefs;
CHECK(prefs.Init(power_manager::Prefs::GetDefaultStore(),
power_manager::Prefs::GetDefaultSources()));
power_manager::system::UdevStub udev;
power_manager::system::DBusWrapperStub dbus_wrapper;
base::FilePath path(power_manager::kPowerStatusPath);
auto battery_percentage_converter =
power_manager::BatteryPercentageConverter::CreateFromPrefs(&prefs);
power_manager::system::PowerSupply power_supply;
power_supply.Init(path, &prefs, &udev, &dbus_wrapper,
battery_percentage_converter.get());
CHECK(power_supply.RefreshImmediately());
const PowerStatus status = power_supply.GetPowerStatus();
// NOTE, autotests (see autotest/files/client/cros/power_status.py) rely on
// parsing this information below.
// DO NOT CHANGE formatting without also fixing there as well.
InfoDisplay display;
display.SetIndent(0, 0);
display.PrintString("Device: Line Power");
display.SetIndent(2, kFieldNameColumns);
display.PrintValue("path", status.line_power_path);
display.PrintStringValue("online", BoolToString(status.line_power_on));
display.PrintStringValue("type", status.line_power_type);
switch (status.external_power) {
case power_manager::PowerSupplyProperties_ExternalPower_AC:
display.PrintStringValue("enum type", "AC");
break;
case power_manager::PowerSupplyProperties_ExternalPower_USB:
display.PrintStringValue("enum type", "USB");
break;
case power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED:
display.PrintStringValue("enum type", "Disconnected");
break;
default:
display.PrintStringValue("enum type", "Unknown");
}
if (status.has_line_power_voltage)
display.PrintValue("voltage (V)", status.line_power_voltage);
else
display.PrintValue("voltage (V)", "Not available");
if (status.has_line_power_current)
display.PrintValue("current (A)", status.line_power_current);
else
display.PrintValue("current (A)", "Not available");
if (status.has_line_power_max_voltage)
display.PrintValue("max voltage (V)", status.line_power_max_voltage);
else
display.PrintValue("max voltage (V)", "Not available");
if (status.has_line_power_max_current)
display.PrintValue("max current (A)", status.line_power_max_current);
else
display.PrintValue("max current (A)", "Not available");
display.PrintStringValue("active source", status.external_power_source_id);
std::vector<std::string> sources;
for (const auto& port : status.ports) {
if (port.role == PowerStatus::Port::Role::DEDICATED_SOURCE ||
port.role == PowerStatus::Port::Role::DUAL_ROLE) {
sources.push_back(base::StringPrintf(
"%s%s [%s/%s]", port.id.c_str(), port.active_by_default ? "*" : "",
port.manufacturer_id.c_str(), port.model_id.c_str()));
}
}
display.PrintStringValue("available sources",
base::JoinString(sources, ", "));
display.PrintStringValue("supports dual-role",
BoolToString(status.supports_dual_role_devices));
if (status.battery_is_present) {
display.SetIndent(0, 0);
display.PrintString("Device: Battery");
display.SetIndent(2, kFieldNameColumns);
display.PrintValue("path", status.battery_path);
display.PrintStringValue("vendor", status.battery_vendor);
display.PrintStringValue("model name", status.battery_model_name);
switch (status.battery_state) {
case power_manager::PowerSupplyProperties_BatteryState_FULL:
display.PrintStringValue("state", "Fully charged");
break;
case power_manager::PowerSupplyProperties_BatteryState_CHARGING:
display.PrintStringValue("state", "Charging");
break;
case power_manager::PowerSupplyProperties_BatteryState_DISCHARGING:
display.PrintStringValue("state", "Discharging");
break;
case power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT:
display.PrintStringValue("state", "Not present");
break;
default:
display.PrintStringValue("state", "Unknown");
}
display.PrintValue("voltage (V)", status.battery_voltage);
display.PrintValue("energy (Wh)", status.battery_energy);
display.PrintValue("energy rate (W)", status.battery_energy_rate);
display.PrintValue("current (A)", status.battery_current);
display.PrintValue("charge (Ah)", status.battery_charge);
display.PrintValue("full charge (Ah)", status.battery_charge_full);
display.PrintValue("full charge design (Ah)",
status.battery_charge_full_design);
display.PrintValue("percentage", status.battery_percentage);
display.PrintValue("display percentage", status.display_battery_percentage);
display.PrintStringValue("technology", status.battery_technology);
// Don't print the battery time estimates -- they're wildly inaccurate since
// this program only takes a single reading of the current.
}
return 0;
}