From 6ff28d87315e30b068dcb7e67c3d3c2fc74b93ec Mon Sep 17 00:00:00 2001 From: sarahemm Date: Tue, 15 Oct 2024 17:16:46 -0400 Subject: [PATCH] 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 Reviewed-by: waddlesplash Haiku-Format: Haiku-format Bot --- src/apps/powerstatus/PowerStatusView.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/apps/powerstatus/PowerStatusView.cpp b/src/apps/powerstatus/PowerStatusView.cpp index fc1a20a210..dbe2b5b842 100644 --- a/src/apps/powerstatus/PowerStatusView.cpp +++ b/src/apps/powerstatus/PowerStatusView.cpp @@ -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; + } } }