BatteryProviderUPower.cpp [plain text]
#include "config.h"
#include "BatteryProviderUPower.h"
#if ENABLE(BATTERY_STATUS)
#include "BatteryProviderUPowerClient.h"
#include <cmath>
#include <limits>
#include <wtf/gobject/GUniquePtr.h>
using namespace WebCore;
static void powerDeviceAlterationCallback(UpClient* upowerClient, UpDevice* upowerDevice, BatteryProviderUPower* provider)
{
UpDeviceKind deviceKind;
g_object_get(upowerDevice, "kind", &deviceKind, nullptr);
if (deviceKind != UP_DEVICE_KIND_BATTERY)
return;
provider->updateBatteryStatus();
}
BatteryProviderUPower::BatteryProviderUPower(BatteryProviderUPowerClient* client)
: m_client(client)
, m_isUpdating(false)
{
ASSERT(m_client);
}
void BatteryProviderUPower::startUpdating()
{
ASSERT(!m_upowerClient);
m_upowerClient = adoptGRef(up_client_new());
GUniqueOutPtr<GError> error;
if (!up_client_enumerate_devices_sync(m_upowerClient.get(), 0, &error.outPtr())) {
m_client->updateBatteryStatus(NotAvailable);
return;
}
g_signal_connect(m_upowerClient.get(), "device-changed", G_CALLBACK(powerDeviceAlterationCallback), this);
g_signal_connect(m_upowerClient.get(), "device-added", G_CALLBACK(powerDeviceAlterationCallback), this);
g_signal_connect(m_upowerClient.get(), "device-removed", G_CALLBACK(powerDeviceAlterationCallback), this);
m_isUpdating = true;
updateBatteryStatus();
}
void BatteryProviderUPower::stopUpdating()
{
m_upowerClient.clear();
m_isUpdating = false;
}
void BatteryProviderUPower::updateBatteryStatus()
{
if (!m_isUpdating)
return;
GPtrArray* devices = up_client_get_devices(m_upowerClient.get());
if (!devices) {
m_client->updateBatteryStatus(NotAvailable);
return;
}
unsigned numOfBatteryDevices = 0;
double combinedEnergyCapacityCurrent = 0, combinedEnergyCapacityFull = 0, combinedEnergyRate = 0;
for (unsigned i = 0; i < devices->len; i++) {
UpDevice* device = static_cast<UpDevice*>(g_ptr_array_index(devices, i));
UpDeviceKind deviceKind;
UpDeviceState deviceState;
bool isPresent;
double energyCapacityCurrent = 0, energyCapacityEmpty = 0, energyCapacityFull = 0, energyRate = 0;
g_object_get(device,
"energy", &energyCapacityCurrent,
"energy-empty", &energyCapacityEmpty,
"energy-full", &energyCapacityFull,
"energy-rate", &energyRate,
"is-present", &isPresent,
"kind", &deviceKind,
"state", &deviceState,
nullptr);
if (deviceKind != UP_DEVICE_KIND_BATTERY || !isPresent)
continue;
numOfBatteryDevices++;
combinedEnergyCapacityCurrent += energyCapacityCurrent - energyCapacityEmpty;
combinedEnergyCapacityFull += energyCapacityFull;
combinedEnergyRate += deviceState == UP_DEVICE_STATE_DISCHARGING ? -energyRate : energyRate;
}
g_ptr_array_unref(devices);
if (!numOfBatteryDevices) {
m_client->updateBatteryStatus(NotAvailable);
return;
}
double level = 0;
if (combinedEnergyCapacityFull > 0)
level = combinedEnergyCapacityCurrent / combinedEnergyCapacityFull;
if (combinedEnergyRate >= 0) {
double chargingTime = std::numeric_limits<double>::infinity();
if (combinedEnergyRate)
chargingTime = 3600 * (combinedEnergyCapacityFull - combinedEnergyCapacityCurrent) / combinedEnergyRate;
m_client->updateBatteryStatus(Charging, chargingTime, level);
} else {
double dischargingTime = 3600 * combinedEnergyCapacityCurrent / std::abs(combinedEnergyRate);
m_client->updateBatteryStatus(Discharging, dischargingTime, level);
}
}
#endif // ENABLE(BATTERY_STATUS)