blob: 61663170898597cd5e68394580a2f273dd357b3b [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.
#ifndef POWER_MANAGER_POWERD_SYSTEM_POWER_SUPPLY_H_
#define POWER_MANAGER_POWERD_SYSTEM_POWER_SUPPLY_H_
#include <string>
#include <base/basictypes.h>
#include <base/cancelable_callback.h>
#include <base/files/file_path.h>
#include <base/memory/scoped_ptr.h>
#include <base/observer_list.h>
#include <base/time/time.h>
#include <base/timer/timer.h>
#include "power_manager/powerd/system/power_supply_observer.h"
#include "power_manager/powerd/system/rolling_average.h"
#include "power_manager/powerd/system/udev_observer.h"
#include "power_manager/proto_bindings/power_supply_properties.pb.h"
namespace power_manager {
class Clock;
class PrefsInterface;
namespace system {
class UdevInterface;
// Structures used for passing power supply info.
struct PowerStatus {
PowerStatus()
: line_power_on(false),
line_power_voltage(0.0),
line_power_current(0.0),
battery_energy(0.0),
battery_energy_rate(0.0),
battery_voltage(0.0),
battery_current(0.0),
battery_charge(0.0),
battery_charge_full(0.0),
battery_charge_full_design(0.0),
observed_battery_charge_rate(0.0),
nominal_voltage(0.0),
is_calculating_battery_time(false),
battery_percentage(-1.0),
display_battery_percentage(-1.0),
battery_is_present(false),
battery_below_shutdown_threshold(false),
external_power(PowerSupplyProperties_ExternalPower_DISCONNECTED),
battery_state(PowerSupplyProperties_BatteryState_NOT_PRESENT) {}
// Is a non-battery power source connected?
bool line_power_on;
// String read from sysfs describing the non-battery power source.
std::string line_power_type;
// The charger's model name, if applicable and available.
std::string line_power_model_name;
// Line power statistics. These may be unset even if line power is connected.
double line_power_voltage; // In volts.
double line_power_current; // In amperes.
// Amount of energy, measured in Wh, in the battery.
double battery_energy;
// Amount of energy being drained from the battery, measured in W. It is a
// positive value irrespective of the battery charging or discharging.
double battery_energy_rate;
// Current battery levels.
double battery_voltage; // In volts.
double battery_current; // In amperes.
double battery_charge; // In ampere-hours.
// Battery full charge level in ampere-hours.
double battery_charge_full;
// Battery full design charge level in ampere-hours.
double battery_charge_full_design;
// Observed rate at which the battery's charge has been changing, in amperes
// (i.e. change in the charge per hour). Positive if the battery's charge has
// increased, negative if it's decreased, and zero if the charge hasn't
// changed or if the rate was not calculated because too few samples were
// available.
double observed_battery_charge_rate;
// The battery voltage used in calculating time remaining. This may or may
// not be the same as the instantaneous voltage |battery_voltage|, as voltage
// levels vary over the time the battery is charged or discharged.
double nominal_voltage;
// Set to true when we have just transitioned states and we might have both a
// segment of charging and discharging in the calculation. This is done to
// signal that the time value maybe inaccurate.
bool is_calculating_battery_time;
// Estimated time until the battery is empty (while discharging) or full
// (while charging).
base::TimeDelta battery_time_to_empty;
base::TimeDelta battery_time_to_full;
// If discharging, estimated time until the battery is at a low-enough level
// that the system will shut down automatically. This will be less than
// |battery_time_to_empty| if a shutdown threshold is set.
base::TimeDelta battery_time_to_shutdown;
// Battery charge in the range [0.0, 100.0], i.e. |battery_charge| /
// |battery_charge_full| * 100.0.
double battery_percentage;
// Battery charge in the range [0.0, 100.0] that should be displayed to
// the user. This takes other factors into consideration, such as the
// percentage at which point we shut down the device and the "full
// factor".
double display_battery_percentage;
// Does the system have a battery?
bool battery_is_present;
// Is the battery level so low that the machine should be shut down?
bool battery_below_shutdown_threshold;
PowerSupplyProperties_ExternalPower external_power;
PowerSupplyProperties_BatteryState battery_state;
// /sys paths from which the line power and battery information was read.
std::string line_power_path;
std::string battery_path;
// Additional information about the battery.
std::string battery_vendor;
std::string battery_model_name;
std::string battery_serial;
std::string battery_technology;
};
// Fetches the system's power status, e.g. whether on AC or battery, charge and
// voltage level, current, etc.
class PowerSupplyInterface {
public:
PowerSupplyInterface() {}
virtual ~PowerSupplyInterface() {}
// Adds or removes an observer.
virtual void AddObserver(PowerSupplyObserver* observer) = 0;
virtual void RemoveObserver(PowerSupplyObserver* observer) = 0;
// Returns the last-read status.
virtual PowerStatus GetPowerStatus() const = 0;
// Updates the status synchronously, returning true on success. If successful,
// observers will be notified asynchronously.
virtual bool RefreshImmediately() = 0;
// On suspend, stops polling. On resume, updates the status immediately and
// schedules a poll for the near future.
virtual void SetSuspended(bool suspended) = 0;
};
// Real implementation of PowerSupplyInterface that reads from sysfs.
class PowerSupply : public PowerSupplyInterface, public UdevObserver {
public:
// Helper class for testing PowerSupply.
class TestApi {
public:
explicit TestApi(PowerSupply* power_supply) : power_supply_(power_supply) {}
~TestApi() {}
base::TimeDelta current_poll_delay() const {
return power_supply_->current_poll_delay_for_testing_;
}
// Returns the time that will be used as "now".
base::TimeTicks GetCurrentTime() const;
// Sets the time that will be used as "now".
void SetCurrentTime(base::TimeTicks now);
// Advances the time by |interval|.
void AdvanceTime(base::TimeDelta interval);
// If |poll_timer_| was running, calls HandlePollTimeout() and returns true.
// Returns false otherwise.
bool TriggerPollTimeout() WARN_UNUSED_RESULT;
private:
PowerSupply* power_supply_; // weak
DISALLOW_COPY_AND_ASSIGN(TestApi);
};
// Power supply subsystem for udev events.
static const char kUdevSubsystem[];
// Minimum duration of samples that need to be present in |charge_samples_|
// for the observed battery charge rate to be calculated.
static const int kObservedBatteryChargeRateMinMs;
// Additional time beyond |battery_stabilized_after_*_delay_| to wait before
// updating the status, in milliseconds. This just ensures that the timer
// doesn't fire before it's safe to calculate the battery time.
static const int kBatteryStabilizedSlackMs;
// To reduce the risk of shutting down prematurely due to a bad battery
// time-to-empty estimate, avoid shutting down when
// |low_battery_shutdown_time_| is set if the battery percent is not also
// equal to or less than this threshold (in the range [0.0, 100.0)).
static const double kLowBatteryShutdownSafetyPercent;
PowerSupply();
virtual ~PowerSupply();
base::TimeTicks battery_stabilized_timestamp() const {
return battery_stabilized_timestamp_;
}
// Initializes the object and begins polling. Ownership of |prefs| remains
// with the caller.
void Init(const base::FilePath& power_supply_path,
PrefsInterface *prefs,
UdevInterface* udev);
// PowerSupplyInterface implementation:
virtual void AddObserver(PowerSupplyObserver* observer) OVERRIDE;
virtual void RemoveObserver(PowerSupplyObserver* observer) OVERRIDE;
virtual PowerStatus GetPowerStatus() const OVERRIDE;
virtual bool RefreshImmediately() OVERRIDE;
virtual void SetSuspended(bool suspended) OVERRIDE;
// UdevObserver implementation:
virtual void OnUdevEvent(const std::string& subsystem,
const std::string& sysname,
UdevObserver::Action action) OVERRIDE;
private:
// Returns the value of |pref_name|, an int64 pref containing a
// millisecond-based duration. |default_duration_ms| is returned if the pref
// is unset.
base::TimeDelta GetMsPref(const std::string& pref_name,
int64 default_duration_ms) const;
// Sets |battery_stabilized_timestamp_| so that the current and charge won't
// be sampled again until at least |stabilized_delay| in the future.
void DeferBatterySampling(base::TimeDelta stabilized_delay);
// Read data from power supply sysfs and fill out all fields of the
// PowerStatus structure if possible.
bool UpdatePowerStatus();
// Find sysfs directories to read from.
void GetPowerSupplyPaths();
// Updates |status|'s time-to-full and time-to-empty estimates or returns
// false if estimates can't be calculated yet. Negative values are used
// if the estimates would otherwise be extremely large (due to a very low
// current).
//
// The |battery_state|, |battery_charge|, |battery_charge_full|,
// |nominal_voltage|, and |battery_voltage| fields must already be
// initialized.
bool UpdateBatteryTimeEstimates(PowerStatus* status);
// Calculates and stores the observed (based on periodic sampling) rate at
// which the battery's reported charge is changing.
void UpdateObservedBatteryChargeRate(PowerStatus* status) const;
// Returns true if |status|'s battery level is so low that the system
// should be shut down. |status|'s |battery_percentage|,
// |battery_time_to_*|, and |line_power_on| fields must already be set.
bool IsBatteryBelowShutdownThreshold(const PowerStatus& status) const;
// Schedules |poll_timer_| to call HandlePollTimeout().
void SchedulePoll();
// Handles |poll_timer_| firing. Updates |power_status_| and reschedules the
// timer.
void HandlePollTimeout();
// Notifies |observers_| that |power_status_| has been updated.
void NotifyObservers();
PrefsInterface* prefs_; // non-owned
UdevInterface* udev_; // non-owned
scoped_ptr<Clock> clock_;
ObserverList<PowerSupplyObserver> observers_;
// Most-recently-computed status.
PowerStatus power_status_;
// True after |power_status_| has been successfully updated at least once.
bool power_status_initialized_;
// Paths to power supply base sysfs directory and battery and line power
// subdirectories.
base::FilePath power_supply_path_;
base::FilePath line_power_path_;
base::FilePath battery_path_;
// Remaining battery time at which the system will shut down automatically.
// Empty if unset.
base::TimeDelta low_battery_shutdown_time_;
// Remaining battery charge (as a percentage of |battery_charge_full| in the
// range [0.0, 100.0]) at which the system will shut down automatically. 0.0
// if unset. If both |low_battery_shutdown_time_| and this setting are
// supplied, only |low_battery_shutdown_percent_| will take effect.
double low_battery_shutdown_percent_;
bool is_suspended_;
// Amount of time to wait after startup, a power source change, or a
// resume event before assuming that the current can be used in battery
// time estimates and the charge is accurate.
base::TimeDelta battery_stabilized_after_startup_delay_;
base::TimeDelta battery_stabilized_after_line_power_connected_delay_;
base::TimeDelta battery_stabilized_after_line_power_disconnected_delay_;
base::TimeDelta battery_stabilized_after_resume_delay_;
// Time at which the reported current and charge are expected to have
// stabilized to the point where they can be recorded in
// |current_samples_on_*_power_| and |charge_samples_| and the battery's
// time-to-full or time-to-empty estimates can be updated.
base::TimeTicks battery_stabilized_timestamp_;
// A collection of recent current readings (in amperes) used to calculate
// time-to-full and time-to-empty estimates collected while on line or
// battery power. Values are positive when the battery is charging and
// negative when it's discharging.
scoped_ptr<RollingAverage> current_samples_on_line_power_;
scoped_ptr<RollingAverage> current_samples_on_battery_power_;
// A collection of recent charge readings (in ampere-hours) used to measure
// the rate at which the battery is charging or discharging. Reset when the
// system resumes from suspend or the power source changes.
scoped_ptr<RollingAverage> charge_samples_;
// The fraction of the full charge at which the battery is considered "full",
// in the range (0.0, 1.0]. Initialized from kPowerSupplyFullFactorPref.
double full_factor_;
// Amount of time to wait before updating |power_status_| again after an
// update.
base::TimeDelta poll_delay_;
// Calls HandlePollTimeout().
base::OneShotTimer<PowerSupply> poll_timer_;
// Delay used when |poll_timer_| was last started.
base::TimeDelta current_poll_delay_for_testing_;
// Calls NotifyObservers().
base::CancelableClosure notify_observers_task_;
DISALLOW_COPY_AND_ASSIGN(PowerSupply);
};
} // namespace system
} // namespace power_manager
#endif // POWER_MANAGER_POWERD_SYSTEM_POWER_SUPPLY_H_