summaryrefslogtreecommitdiffstats
path: root/xbmc/platform/linux/powermanagement/UPowerSyscall.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/platform/linux/powermanagement/UPowerSyscall.cpp')
-rw-r--r--xbmc/platform/linux/powermanagement/UPowerSyscall.cpp207
1 files changed, 207 insertions, 0 deletions
diff --git a/xbmc/platform/linux/powermanagement/UPowerSyscall.cpp b/xbmc/platform/linux/powermanagement/UPowerSyscall.cpp
new file mode 100644
index 0000000..27ed2f4
--- /dev/null
+++ b/xbmc/platform/linux/powermanagement/UPowerSyscall.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "UPowerSyscall.h"
+
+#include "utils/log.h"
+
+CUPowerSource::CUPowerSource(const char *powerSource)
+{
+ if(powerSource == NULL)
+ m_powerSource = "";
+ else
+ m_powerSource = powerSource;
+
+ CVariant properties = CDBusUtil::GetAll("org.freedesktop.UPower", m_powerSource.c_str(), "org.freedesktop.UPower.Device");
+ m_isRechargeable = properties["IsRechargeable"].asBoolean();
+ Update();
+}
+
+CUPowerSource::~CUPowerSource() = default;
+
+void CUPowerSource::Update()
+{
+ CVariant properties = CDBusUtil::GetAll("org.freedesktop.UPower", m_powerSource.c_str(), "org.freedesktop.UPower.Device");
+ m_batteryLevel = properties["Percentage"].asDouble();
+}
+
+bool CUPowerSource::IsRechargeable()
+{
+ return m_isRechargeable;
+}
+
+double CUPowerSource::BatteryLevel()
+{
+ return m_batteryLevel;
+}
+
+CUPowerSyscall::CUPowerSyscall()
+{
+ CLog::Log(LOGINFO, "Selected UPower as PowerSyscall");
+
+ m_lowBattery = false;
+
+ //! @todo do not use dbus_connection_pop_message() that requires the use of a
+ //! private connection
+ if (m_connection.Connect(DBUS_BUS_SYSTEM, true))
+ {
+ dbus_connection_set_exit_on_disconnect(m_connection, false);
+
+ CDBusError error;
+ dbus_bus_add_match(m_connection, "type='signal',interface='org.freedesktop.UPower'", error);
+ dbus_connection_flush(m_connection);
+
+ if (error)
+ {
+ error.Log("UPower: Failed to attach to signal");
+ m_connection.Destroy();
+ }
+ }
+
+ m_CanPowerdown = false;
+ m_CanReboot = false;
+
+ UpdateCapabilities();
+
+ EnumeratePowerSources();
+}
+
+bool CUPowerSyscall::Powerdown()
+{
+ return false;
+}
+
+bool CUPowerSyscall::Suspend()
+{
+ // UPower 0.9.1 does not signal sleeping unless you tell that its about to sleep...
+ CDBusMessage aboutToSleepMessage("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "AboutToSleep");
+ aboutToSleepMessage.SendAsyncSystem();
+
+ CDBusMessage message("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "Suspend");
+ return message.SendAsyncSystem();
+}
+
+bool CUPowerSyscall::Hibernate()
+{
+ // UPower 0.9.1 does not signal sleeping unless you tell that its about to sleep...
+ CDBusMessage aboutToSleepMessage("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "AboutToSleep");
+ aboutToSleepMessage.SendAsyncSystem();
+
+ CDBusMessage message("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "Hibernate");
+ return message.SendAsyncSystem();
+}
+
+bool CUPowerSyscall::Reboot()
+{
+ return false;
+}
+
+bool CUPowerSyscall::CanPowerdown()
+{
+ return m_CanPowerdown;
+}
+
+bool CUPowerSyscall::CanSuspend()
+{
+ return m_CanSuspend;
+}
+
+bool CUPowerSyscall::CanHibernate()
+{
+ return m_CanHibernate;
+}
+
+bool CUPowerSyscall::CanReboot()
+{
+ return m_CanReboot;
+}
+
+int CUPowerSyscall::BatteryLevel()
+{
+ unsigned int nBatteryCount = 0;
+ double subCapacity = 0;
+ double batteryLevel = 0;
+
+ for (auto& itr : m_powerSources)
+ {
+ itr.Update();
+ if (itr.IsRechargeable())
+ {
+ nBatteryCount++;
+ subCapacity += itr.BatteryLevel();
+ }
+ }
+
+ if(nBatteryCount)
+ batteryLevel = subCapacity / (double)nBatteryCount;
+
+ return (int) batteryLevel;
+}
+
+void CUPowerSyscall::EnumeratePowerSources()
+{
+ CDBusMessage message("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "EnumerateDevices");
+ DBusMessage *reply = message.SendSystem();
+ if (reply)
+ {
+ char** source = NULL;
+ int length = 0;
+
+ if (dbus_message_get_args (reply, NULL, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &source, &length, DBUS_TYPE_INVALID))
+ {
+ for (int i = 0; i < length; i++)
+ {
+ m_powerSources.emplace_back(source[i]);
+ }
+
+ dbus_free_string_array(source);
+ }
+ }
+}
+
+bool CUPowerSyscall::HasUPower()
+{
+ return CDBusUtil::TryMethodCall(DBUS_BUS_SYSTEM, "org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "EnumerateDevices");
+}
+
+bool CUPowerSyscall::PumpPowerEvents(IPowerEventsCallback *callback)
+{
+ bool result = false;
+
+ if (m_connection)
+ {
+ dbus_connection_read_write(m_connection, 0);
+ DBusMessagePtr msg(dbus_connection_pop_message(m_connection));
+
+ if (msg)
+ {
+ result = true;
+ if (dbus_message_is_signal(msg.get(), "org.freedesktop.UPower", "Sleeping"))
+ callback->OnSleep();
+ else if (dbus_message_is_signal(msg.get(), "org.freedesktop.UPower", "Resuming"))
+ callback->OnWake();
+ else if (dbus_message_is_signal(msg.get(), "org.freedesktop.UPower", "Changed"))
+ {
+ bool lowBattery = m_lowBattery;
+ UpdateCapabilities();
+ if (m_lowBattery && !lowBattery)
+ callback->OnLowBattery();
+ }
+ else
+ CLog::Log(LOGDEBUG, "UPower: Received an unknown signal {}",
+ dbus_message_get_member(msg.get()));
+ }
+ }
+ return result;
+}
+
+void CUPowerSyscall::UpdateCapabilities()
+{
+ m_CanSuspend = CDBusUtil::GetVariant("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "CanSuspend").asBoolean(false);
+ m_CanHibernate = CDBusUtil::GetVariant("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "CanHibernate").asBoolean(false);
+}