diff --git a/src/linux/integration-test.py b/src/linux/integration-test.py index cd3cb74..e28f1a3 100755 --- a/src/linux/integration-test.py +++ b/src/linux/integration-test.py @@ -561,6 +561,43 @@ class Tests(dbusmock.DBusTestCase): self.assertAlmostEqual(self.get_dbus_dev_property(bat0_up, "Percentage"), 80.0) + def test_macbook_energy_full_blip(self): + '''Value blip issue for Macbooks''' + + ac = self.testbed.add_device('power_supply', 'AC', None, + ['type', 'Mains', 'online', '0'], []) + bat0 = self.testbed.add_device('power_supply', 'BAT0', None, + ['type', 'Battery', + 'present', '1', + 'status', 'Discharging', + 'capacity', '60', + 'energy_full', '60000000', + 'energy_full_design', '80000000', + 'energy_now', '48000000', + 'voltage_now', '12000000'], []) + self.testbed.add_device('virtual', 'virtual/dmi', None, + ['id/product_name', 'MacBookAir7,2'], []) + self.start_daemon() + devs = self.proxy.EnumerateDevices() + self.assertEqual(len(devs), 2) + if 'BAT' in devs[0] == ac_up: + (bat0_up, ac_up) = devs + else: + (ac_up, bat0_up) = devs + + # blip + self.testbed.set_attribute(bat0, 'energy_full', '600000000') + self.testbed.set_attribute(bat0, 'energy_now', '480000000') + self.testbed.uevent(bat0, 'change') + self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), 80) + + # go back to normal + self.testbed.set_attribute(bat0, 'energy_full', '60000000') + self.testbed.set_attribute(bat0, 'energy_now', '48000000') + self.testbed.uevent(bat0, 'change') + self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), 80) + + def test_macbook_uevent(self): """MacBooks sent uevent 5 seconds before battery updates""" diff --git a/src/up-device-battery.c b/src/up-device-battery.c index 0e51aab..5f2d6e5 100644 --- a/src/up-device-battery.c +++ b/src/up-device-battery.c @@ -46,6 +46,7 @@ typedef struct { gdouble energy_design; gint charge_cycles; + gboolean always_update_energy_full; gboolean trust_power_measurement; gint64 last_power_discontinuity; @@ -310,6 +311,13 @@ up_device_battery_report (UpDeviceBattery *self, "capacity", MIN (priv->energy_full / priv->energy_design * 100.0, 100), "energy-full", priv->energy_full, NULL); + + /* QUIRK: + * + * Some Macbook Airs have a short blip where both energy_full and energy.cur + * are scaled up by some factor. However, they both eventually return back + * to normal, so energy_full must be updated. */ + priv->always_update_energy_full = TRUE; } /* Infer percentage if unknown */ @@ -567,7 +575,7 @@ up_device_battery_update_info (UpDeviceBattery *self, UpBatteryInfo *info) /* Force -1 for unknown value (where 0 is also an unknown value) */ charge_cycles = info->charge_cycles > 0 ? info->charge_cycles : -1; - if (energy_full != priv->energy_full_reported || energy_design != priv->energy_design) { + if (energy_full != priv->energy_full_reported || energy_design != priv->energy_design || (priv->always_update_energy_full && energy_full != priv->energy_full)) { priv->energy_full = energy_full; priv->energy_full_reported = energy_full; priv->energy_design = energy_design;