PowerStatus: Fix time left and spurious low-battery alerts with >1 battery

1. Only do low battery processing if the battery being queried is the
   "virtual aggregate battery" (ID -1), this fixes the issue of spurious
   and duplicated low battery warnings whenever the extended info panel is
   open (and therefore multiple batteries are being individually queried).

2. Calculate the time remaining separately after adding up all the
   individual battery values, this works around batteries which are not
   currently in use returning -1 time_left which caused the aggregate to be
   incorrect if the values from the driver interface are simply added as-is.

An example situation to illustrate item 2:
Battery 0 capacity: 20,000mWh
Battery 0 draw: 0mW
Battery 0 state: Unused
Battery 0 time_left: -1 (since it currently has zero draw on it, it has
	"infinite time left" if looked at in isolation)

Battery 1 capacity: 20,000mWh
Battery 1 draw: 10,000mW
Battery 1 state: Discharging
Battery 1 time_left: 2 hours

If the time_lefts are added together (even if battery 0 is ignored for that
calculation), it'll show 2 hours left despite there being 40,000mWh of total
capacity for a 10,000mW draw. We now treat all batteries together as one large
one instead, calculating the draw/capacity on the totals which gives an
accurate number.

This fixes issues 2 and 3 in bug #19167.

Change-Id: I1b9a0c3dd47f917da86becfcfebed7b35b3422d4
Reviewed-on: https://review.haiku-os.org/c/haiku/+/8462
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
Haiku-Format: Haiku-format Bot <no-reply+haikuformatbot@haiku-os.org>
This commit is contained in:
sarahemm 2024-10-15 17:16:46 -04:00 committed by waddlesplash
parent c3c6ee24b0
commit 6ff28d8731

View File

@ -525,6 +525,10 @@ PowerStatusView::Update(bool force, bool notify)
Invalidate();
}
// only do low battery notices based on the aggregate virtual battery, not single batteries
if (fBatteryID >= 0)
return;
if (fPercent > kLowBatteryPercentage && fTimeLeft > kLowBatteryTimeLeft)
fHasNotifiedLowBattery = false;
@ -594,7 +598,6 @@ PowerStatusView::_GetBatteryInfo(int batteryID, battery_info* batteryInfo)
for (int i = 0; i < fDriverInterface->GetBatteryCount(); i++) {
battery_info info;
fDriverInterface->GetBatteryInfo(i, &info);
if (info.full_capacity <= 0)
continue;
@ -605,9 +608,25 @@ PowerStatusView::_GetBatteryInfo(int batteryID, battery_info* batteryInfo)
batteryInfo->state |= info.state;
batteryInfo->capacity += info.capacity;
batteryInfo->full_capacity += info.full_capacity;
batteryInfo->time_left += info.time_left;
batteryInfo->current_rate += info.current_rate;
}
}
// we can't rely on just adding the individual batteries' time_lefts together:
// not-in-use batteries show -1 time_left as they will last infinitely long with their
// current (zero) level of draw, despite them being in the queue to use after the current
// battery is out of energy. therefore to calculate an accurate time, we have to use the
// current total rate of (dis)charge compared to the total remaining capacity of all
// batteries.
if (batteryInfo->current_rate == 0) {
// some systems briefly return current_rate of 0 as the charger is plugged/unplugged
batteryInfo->time_left = 0;
} else if ((batteryInfo->state & BATTERY_CHARGING) != 0) {
batteryInfo->time_left = 3600 * (batteryInfo->full_capacity - batteryInfo->capacity)
/ batteryInfo->current_rate;
} else {
batteryInfo->time_left = 3600 * batteryInfo->capacity / batteryInfo->current_rate;
}
}
}