diff --git a/src/up-daemon.c b/src/up-daemon.c index 38d49d5..ca780b2 100644 --- a/src/up-daemon.c +++ b/src/up-daemon.c @@ -169,6 +169,8 @@ up_daemon_update_display_battery (UpDaemon *daemon) gdouble percentage = 0.0; gdouble energy = 0.0; gdouble energy_full = 0.0; + gdouble energy_full_design = 0.0; + gdouble effective_energy_full = 0.0; gdouble energy_rate = 0.0; gint64 time_to_empty = 0; gint64 time_to_full = 0; @@ -183,6 +185,7 @@ up_daemon_update_display_battery (UpDaemon *daemon) "percentage", &percentage, "energy", &energy, "energy-full", &energy_full, + "energy-full-design", &energy_full_design, "energy-rate", &energy_rate, "time-to-empty", &time_to_empty, "time-to-full", &time_to_full, @@ -253,11 +256,39 @@ up_daemon_update_display_battery (UpDaemon *daemon) /* If at least one battery has charge thresholds enabled, propagate that. */ charge_threshold_enabled_total = charge_threshold_enabled_total || charge_threshold_enabled; - /* sum up composite */ + /* Validate battery capacity data before aggregation. + * Some firmware/ACPI implementations report energy_full=0 due to bugs, + * which breaks the weighted percentage calculation. We fall back to + * energy_full_design if available, or skip the battery from capacity-based + * calculation (will use percentage averaging instead). + */ + + if (energy_full >= 0.01) { + /* Primary: Use reported full capacity */ + effective_energy_full = energy_full; + } else if (energy_full_design >= 0.01) { + /* Fallback: Use design capacity */ + effective_energy_full = energy_full_design; + g_debug ("Battery reports invalid energy_full (%.4f Wh), " + "using energy_full_design=%.2f Wh as fallback", + energy_full, energy_full_design); + } else { + /* No valid capacity data - skip from energy-based calculation. + * The percentage averaging fallback will be used instead. + */ + g_warning ("Battery reports energy=%.2f Wh but both energy_full and " + "energy_full_design are invalid; excluding from composite " + "capacity calculation", energy); + percentage_total += percentage; + num_batteries++; + continue; + } + + /* Sum up composite using validated capacity data */ kind_total = UP_DEVICE_KIND_BATTERY; is_present_total = TRUE; energy_total += energy; - energy_full_total += energy_full; + energy_full_total += effective_energy_full; energy_rate_total += energy_rate; time_to_empty_total += time_to_empty; time_to_full_total += time_to_full; @@ -273,8 +304,9 @@ up_daemon_update_display_battery (UpDaemon *daemon) g_debug ("Calculating percentage and time to full/to empty for %i batteries", num_batteries); /* use percentage weighted for each battery capacity - * fall back to averaging the batteries. - * ASSUMPTION: If one battery has energy data, then all batteries do + * Fall back to averaging the batteries if capacity data is unavailable. + * NOTE: We now validate capacity data per-battery, as some firmware/ACPI + * implementations incorrectly report energy_full=0. */ if (energy_full_total > 0.0) percentage_total = 100.0 * energy_total / energy_full_total;