Chrome OS Power Supplies

powerd's PowerSupply class is responsible for reading information about power supplies (e.g. line power and batteries) from device directories under /sys/class/power_supply in sysfs. The kernel documentation contains incomplete information about these directories.

Polling

powerd reads power supply information at startup and then polls periodically at 30-second intervals. The information is also refreshed immediately in response to several events:

  • Resume (after suspending)
  • udev events concerning the power_supply subsystem

The information is copied to PowerSupplyProperties protocol buffers that are included in PowerSupplyPoll D-Bus signals.

Line Power

“Line power” refers to chargers or other external power sources; it's sometimes also referred to as “AC” in the code. Information about line power sources is read by PowerSupply::ReadLinePowerDirectory. The following sysfs nodes are particularly relevant:

  • type describes the connected device's type. Notable values include:
    • Unknown - A sink-only device that can't supply power to the Chrome OS device.
    • Mains - A dedicated charger or direct power source. Most pre-USB-C chargers use this type. This type may also appear in conjunction with an online value of 0 when nothing is connected to a dedicated charging port on a pre-USB-C device.
    • USB, USB_ACA, USB_CDP, USB_DCP - A low-power USB BC1.2 power supply. USB-C ports with nothing connected to them may report a USB type in conjunction with an online value of 0.
    • USB_C, USB_PD - A USB Type-C power supply.
    • USB_PD_DRP - A dual-role USB Type-C device (i.e. one capable of either delivering or receiving power).
    • BrickID - An Apple legacy USB charger. May be either USB-A or USB-C.
  • online typically describes whether anything is connected to the port; a value of 1 indicates a connection. If type is USB_PD_DRP, an online value of 0 indicates that a dual-role device is connected but that it is not currently delivering power to the Chrome OS device.
  • status describes the status of a bidirectional/dual-role port. The node is expected to be nonexistent or to contain an empty value for non-dual-role ports. If the node is present, a value of Charging indicates that the port is delivering power to the Chrome OS device.
  • voltage_max_design and current_max are used to compute the maximum power that can be delivered by the power supply.
  • voltage_now and current_now are used to compute the instantaneous power.

Multiple sources

If multiple line power directories are found, powerd will report all of them. This typically happens in the case of Chrome OS devices with multiple USB Type-C ports.

Only one power source may deliver power at a given time; Chrome displays the active source at chrome://settings/power. If multiple sources are available, the user may use this page to select which one to use. Chrome makes a SetPowerSource D-Bus method call to powerd containing the ID of the desired source (taken from an earlier PowerSupplyProperties protobuf), and PowerSupply::SetPowerSource writes 0 to the device‘s charge_control_limit_max sysfs node. Chrome can also pass an empty ID to switch to battery power; powerd writes -1 to the active power source’s node in this case.

Batteries

Battery information is read by PowerSupply::ReadBatteryDirectory. The following sysfs nodes are relevant:

  • status describes the battery‘s current status. The kernel documentation describes possible values. powerd does not distinguish between Charging and Full and instead uses the battery’s reported charge to determine if it is full.
  • voltage_now contains the instantaneous voltage.
  • voltage_min_design and voltage_max_design are read to determine the nominal voltage.
  • current_now, charge_now, and charge_full are read on charge_battery systems to get the battery's current and charge.
  • power_now, energy_now, and energy_full are read on energy_battery systems to get the battery's current and charge.

Percentage and state

PowerSupply::UpdateBatteryPercentagesAndState uses the above information to determine the battery status and charge that should be displayed by the UI. Many batteries charge more slowly as they approach a full charge, so the power_supply_full_factor powerd pref is used to set the charge percentage at which powerd should report the battery as fully-charged. Similarly, powerd will automatically shut the system down before the battery has fully discharged, so the displayed percentage is also scaled based on the low_battery_shutdown_percent pref.

Starting from M92 crrev/c/2984168, on start-up, powerd tries to read low_battery_shutdown_percent and full_factor from CrOS EC using EC_CMD_DISPLAY_SOC. PowerSupply::UpdateBatteryPercentagesAndState also reads the display SoC (state of charge) from CrOS EC using EC_CMD_DISPLAY_SOC. If the command isn't available, the display SoC is computed by powerd using low_battery_shutdown_percent and full_factor read from the pref directories.

Time-to-empty and time-to-full

PowerSupply::UpdateBatteryTimeEstimates attempts to estimate the time until the battery will be fully charged or until the system will shut down due to a low charge. To do this, PowerSupply maintains a rolling average of samples of the battery‘s current. Sampling is temporarily deferred after events like system resume, but these estimates may still be noisy, particularly when the system’s workload is changing frequently.

The Battery Notifications document contains more information about how these estimates are computed and used.

Multiple batteries

If the multiple_batteries pref is set, powerd will use PowerSupply::ReadMultipleBatteryDirectories to read multiple battery power supply directories if present. Most statistics, including the charge and full charge, are just summed across all batteries. If any batteries are charging, the overall state is reported as charging. The UI doesn't currently differentiate between a single battery and multiple batteries; the main difference in the latter scenario is that the displayed charge percentage may change when a battery is connected or disconnected.