blob: 548e31bc6e1874776ee2d44912fa44b989aef1ab [file] [log] [blame]
/*
* Copyright (C) 2012 Samsung Electronics
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "config.h"
#include "BatteryProviderEfl.h"
#if ENABLE(BATTERY_STATUS)
#include "BatteryProviderEflClient.h"
#include "EventNames.h"
#include <limits>
namespace WebCore {
const char BUS[] = "org.freedesktop.UPower";
BatteryProviderEfl::BatteryProviderEfl(BatteryProviderEflClient* client)
: m_client(client)
, m_connection(nullptr)
, m_object(nullptr)
, m_proxy(nullptr)
, m_signalHandler(nullptr)
{
}
BatteryProviderEfl::~BatteryProviderEfl()
{
}
BatteryStatus* BatteryProviderEfl::batteryStatus() const
{
return m_batteryStatus.get();
}
void BatteryProviderEfl::stopUpdating()
{
if (m_signalHandler) {
eldbus_signal_handler_del(m_signalHandler);
m_signalHandler = nullptr;
}
if (m_proxy) {
eldbus_proxy_unref(m_proxy);
m_proxy = nullptr;
}
if (m_object) {
eldbus_object_unref(m_object);
m_object = nullptr;
}
if (m_connection) {
eldbus_connection_unref(m_connection);
m_connection = nullptr;
}
}
static void batteryProperties(void* data, const Eldbus_Message* message, Eldbus_Pending*)
{
if (eldbus_message_error_get(message, nullptr, nullptr))
return;
Eldbus_Message_Iter* array;
if (!eldbus_message_arguments_get(message, "a{sv}", &array))
return;
BatteryProviderEfl* client = static_cast<BatteryProviderEfl*>(data);
BatteryStatus* clientBatteryStatus = client->batteryStatus();
bool charging = false;
bool chargingChanged = false;
bool chargingTimeChanged = false;
int64_t chargingTime;
bool dischargingTimeChanged = false;
int64_t dischargingTime;
bool levelChanged = false;
double level;
Eldbus_Message_Iter* dict;
while (eldbus_message_iter_get_and_next(array, 'e', &dict)) {
char* key;
Eldbus_Message_Iter* variant;
if (!eldbus_message_iter_arguments_get(dict, "sv", &key, &variant))
continue;
if (!strcmp(key, "State")) {
unsigned state;
eldbus_message_iter_arguments_get(variant, "u", &state);
if (state == 1) // Charging
charging = true;
if (!clientBatteryStatus || charging != clientBatteryStatus->charging())
chargingChanged = true;
} else if (!strcmp(key, "TimeToEmpty")) {
eldbus_message_iter_arguments_get(variant, "x", &dischargingTime);
if (!clientBatteryStatus || dischargingTime != clientBatteryStatus->dischargingTime())
dischargingTimeChanged = true;
} else if (!strcmp(key, "TimeToFull")) {
eldbus_message_iter_arguments_get(variant, "x", &chargingTime);
if (!clientBatteryStatus || chargingTime != clientBatteryStatus->chargingTime())
chargingTimeChanged = true;
} else if (!strcmp(key, "Percentage")) {
eldbus_message_iter_arguments_get(variant, "d", &level);
if (!clientBatteryStatus || level != clientBatteryStatus->level() * 100)
levelChanged = true;
}
}
RefPtr<BatteryStatus> batteryStatus = BatteryStatus::create(charging, chargingTime, dischargingTime, level / 100);
if (chargingChanged)
client->setBatteryStatus(eventNames().chargingchangeEvent, batteryStatus);
if (chargingTimeChanged)
client->setBatteryStatus(eventNames().chargingtimechangeEvent, batteryStatus);
if (dischargingTimeChanged)
client->setBatteryStatus(eventNames().dischargingtimechangeEvent, batteryStatus);
if (levelChanged)
client->setBatteryStatus(eventNames().levelchangeEvent, batteryStatus);
}
static void batteryPropertiesChanged(void* data, const Eldbus_Message*)
{
Eldbus_Proxy* proxy = static_cast<Eldbus_Proxy*>(data);
BatteryProviderEfl* provider = static_cast<BatteryProviderEfl*>(eldbus_proxy_data_get(proxy, "_provider"));
eldbus_proxy_property_get_all(proxy, batteryProperties, provider);
}
void BatteryProviderEfl::deviceTypeCallback(void* data, const Eldbus_Message* message, Eldbus_Pending*)
{
if (eldbus_message_error_get(message, nullptr, nullptr))
return;
Eldbus_Message_Iter* variant;
if (!eldbus_message_arguments_get(message, "v", &variant))
return;
unsigned type = 0;
eldbus_message_iter_arguments_get(variant, "u", &type);
if (type != 2)
return;
Eldbus_Proxy* proxy = static_cast<Eldbus_Proxy*>(data);
BatteryProviderEfl* provider = static_cast<BatteryProviderEfl*>(eldbus_proxy_data_get(proxy, "_provider"));
eldbus_proxy_property_get_all(proxy, batteryProperties, provider);
provider->setSignalHandler(eldbus_proxy_signal_handler_add(proxy, "Changed", batteryPropertiesChanged, proxy));
}
void BatteryProviderEfl::enumerateDevices(void* data, const Eldbus_Message* message, Eldbus_Pending*)
{
if (eldbus_message_error_get(message, nullptr, nullptr))
return;
Eldbus_Message_Iter* array;
if (!eldbus_message_arguments_get(message, "ao", &array))
return;
char* path;
while (eldbus_message_iter_get_and_next(array, 'o', &path)) {
if (!path || !path[0])
break;
Eldbus_Object* object = eldbus_object_get(static_cast<BatteryProviderEfl*>(data)->connection(), BUS, path);
if (!object)
continue;
Eldbus_Proxy* proxy = eldbus_proxy_get(object, "org.freedesktop.UPower.Device");
if (!proxy)
continue;
eldbus_proxy_data_set(proxy, "_provider", data);
eldbus_proxy_property_get(proxy, "Type", deviceTypeCallback, proxy);
}
}
void BatteryProviderEfl::startUpdating()
{
if (m_connection)
return;
if (!eldbus_init())
return;
m_connection = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
EINA_SAFETY_ON_NULL_RETURN(m_connection);
m_object = eldbus_object_get(m_connection, BUS, "/org/freedesktop/UPower");
if (!m_object) {
eldbus_connection_unref(m_connection);
m_connection = nullptr;
return;
}
m_proxy = eldbus_proxy_get(m_object, "org.freedesktop.UPower");
if (!m_proxy) {
eldbus_object_unref(m_object);
m_object = nullptr;
eldbus_connection_unref(m_connection);
m_connection = nullptr;
return;
}
eldbus_proxy_call(m_proxy, "EnumerateDevices", enumerateDevices, this, -1, "");
}
void BatteryProviderEfl::setBatteryStatus(const AtomicString& eventType, PassRefPtr<BatteryStatus> batteryStatus)
{
m_batteryStatus = batteryStatus;
m_client->didChangeBatteryStatus(eventType, m_batteryStatus);
}
}
#endif // BATTERY_STATUS