1 /*************************************************************************** 2 * Copyright (c) 2013 Abdurrahman AVCI <abdurrahmanavci@gmail.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the 16 * Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 ***************************************************************************/ 19 20 #include "PowerManager.h" 21 22 #include "Configuration.h" 23 #include "DaemonApp.h" 24 #include "Messages.h" 25 26 #include <QDBusConnectionInterface> 27 #include <QDBusInterface> 28 #include <QDBusReply> 29 #include <QProcess> 30 31 namespace SDDM { 32 /************************************************/ 33 /* POWER MANAGER BACKEND */ 34 /************************************************/ 35 class PowerManagerBackend { 36 public: PowerManagerBackend()37 PowerManagerBackend() { 38 } 39 ~PowerManagerBackend()40 virtual ~PowerManagerBackend() { 41 } 42 43 virtual Capabilities capabilities() const = 0; 44 45 virtual void powerOff() const = 0; 46 virtual void reboot() const = 0; 47 virtual void suspend() const = 0; 48 virtual void hibernate() const = 0; 49 virtual void hybridSleep() const = 0; 50 }; 51 52 /**********************************************/ 53 /* UPOWER BACKEND */ 54 /**********************************************/ 55 56 const QString UPOWER_PATH = QStringLiteral("/org/freedesktop/UPower"); 57 const QString UPOWER_SERVICE = QStringLiteral("org.freedesktop.UPower"); 58 const QString UPOWER_OBJECT = QStringLiteral("org.freedesktop.UPower"); 59 60 class UPowerBackend : public PowerManagerBackend { 61 public: UPowerBackend(const QString & service,const QString & path,const QString & interface)62 UPowerBackend(const QString & service, const QString & path, const QString & interface) { 63 m_interface = new QDBusInterface(service, path, interface, QDBusConnection::systemBus()); 64 } 65 ~UPowerBackend()66 ~UPowerBackend() { 67 delete m_interface; 68 } 69 capabilities() const70 Capabilities capabilities() const { 71 Capabilities caps = Capability::PowerOff | Capability::Reboot; 72 73 QDBusReply<bool> reply; 74 75 // suspend 76 reply = m_interface->call(QStringLiteral("SuspendAllowed")); 77 if (reply.isValid() && reply.value()) 78 caps |= Capability::Suspend; 79 80 // hibernate 81 reply = m_interface->call(QStringLiteral("HibernateAllowed")); 82 if (reply.isValid() && reply.value()) 83 caps |= Capability::Hibernate; 84 85 // return capabilities 86 return caps; 87 } 88 powerOff() const89 void powerOff() const { 90 QProcess::execute(mainConfig.HaltCommand.get()); 91 } 92 reboot() const93 void reboot() const { 94 QProcess::execute(mainConfig.RebootCommand.get()); 95 } 96 suspend() const97 void suspend() const { 98 m_interface->call(QStringLiteral("Suspend")); 99 } 100 hibernate() const101 void hibernate() const { 102 m_interface->call(QStringLiteral("Hibernate")); 103 } 104 hybridSleep() const105 void hybridSleep() const { 106 } 107 108 private: 109 QDBusInterface *m_interface { nullptr }; 110 }; 111 112 /**********************************************/ 113 /* LOGIN1 && ConsoleKit2 BACKEND */ 114 /**********************************************/ 115 116 const QString LOGIN1_SERVICE = QStringLiteral("org.freedesktop.login1"); 117 const QString LOGIN1_PATH = QStringLiteral("/org/freedesktop/login1"); 118 const QString LOGIN1_OBJECT = QStringLiteral("org.freedesktop.login1.Manager"); 119 120 const QString CK2_SERVICE = QStringLiteral("org.freedesktop.ConsoleKit"); 121 const QString CK2_PATH = QStringLiteral("/org/freedesktop/ConsoleKit/Manager"); 122 const QString CK2_OBJECT = QStringLiteral("org.freedesktop.ConsoleKit.Manager"); 123 124 class SeatManagerBackend : public PowerManagerBackend { 125 public: SeatManagerBackend(const QString & service,const QString & path,const QString & interface)126 SeatManagerBackend(const QString & service, const QString & path, const QString & interface) { 127 m_interface = new QDBusInterface(service, path, interface, QDBusConnection::systemBus()); 128 } 129 ~SeatManagerBackend()130 ~SeatManagerBackend() { 131 delete m_interface; 132 } 133 capabilities() const134 Capabilities capabilities() const { 135 Capabilities caps = Capability::None; 136 137 QDBusReply<QString> reply; 138 139 // power off 140 reply = m_interface->call(QStringLiteral("CanPowerOff")); 141 if (reply.isValid() && (reply.value() == QLatin1String("yes"))) 142 caps |= Capability::PowerOff; 143 144 // reboot 145 reply = m_interface->call(QStringLiteral("CanReboot")); 146 if (reply.isValid() && (reply.value() == QLatin1String("yes"))) 147 caps |= Capability::Reboot; 148 149 // suspend 150 reply = m_interface->call(QStringLiteral("CanSuspend")); 151 if (reply.isValid() && (reply.value() == QLatin1String("yes"))) 152 caps |= Capability::Suspend; 153 154 // hibernate 155 reply = m_interface->call(QStringLiteral("CanHibernate")); 156 if (reply.isValid() && (reply.value() == QLatin1String("yes"))) 157 caps |= Capability::Hibernate; 158 159 // hybrid sleep 160 reply = m_interface->call(QStringLiteral("CanHybridSleep")); 161 if (reply.isValid() && (reply.value() == QLatin1String("yes"))) 162 caps |= Capability::HybridSleep; 163 164 // return capabilities 165 return caps; 166 } 167 powerOff() const168 void powerOff() const { 169 m_interface->call(QStringLiteral("PowerOff"), true); 170 } 171 reboot() const172 void reboot() const { 173 if (!daemonApp->testing()) 174 m_interface->call(QStringLiteral("Reboot"), true); 175 } 176 suspend() const177 void suspend() const { 178 m_interface->call(QStringLiteral("Suspend"), true); 179 } 180 hibernate() const181 void hibernate() const { 182 m_interface->call(QStringLiteral("Hibernate"), true); 183 } 184 hybridSleep() const185 void hybridSleep() const { 186 m_interface->call(QStringLiteral("HybridSleep"), true); 187 } 188 189 private: 190 QDBusInterface *m_interface { nullptr }; 191 }; 192 193 /**********************************************/ 194 /* POWER MANAGER */ 195 /**********************************************/ PowerManager(QObject * parent)196 PowerManager::PowerManager(QObject *parent) : QObject(parent) { 197 QDBusConnectionInterface *interface = QDBusConnection::systemBus().interface(); 198 199 // check if login1 interface exists 200 if (interface->isServiceRegistered(LOGIN1_SERVICE)) 201 m_backends << new SeatManagerBackend(LOGIN1_SERVICE, LOGIN1_PATH, LOGIN1_OBJECT); 202 203 // check if ConsoleKit2 interface exists 204 if (interface->isServiceRegistered(CK2_SERVICE)) 205 m_backends << new SeatManagerBackend(CK2_SERVICE, CK2_PATH, CK2_OBJECT); 206 207 // check if upower interface exists 208 if (interface->isServiceRegistered(UPOWER_SERVICE)) 209 m_backends << new UPowerBackend(UPOWER_SERVICE, UPOWER_PATH, UPOWER_OBJECT); 210 } 211 ~PowerManager()212 PowerManager::~PowerManager() { 213 while (!m_backends.empty()) 214 delete m_backends.takeFirst(); 215 } 216 capabilities() const217 Capabilities PowerManager::capabilities() const { 218 Capabilities caps = Capability::None; 219 220 for (PowerManagerBackend *backend: m_backends) 221 caps |= backend->capabilities(); 222 223 return caps; 224 } 225 powerOff() const226 void PowerManager::powerOff() const { 227 if (daemonApp->testing()) 228 return; 229 230 for (PowerManagerBackend *backend: m_backends) { 231 if (backend->capabilities() & Capability::PowerOff) { 232 backend->powerOff(); 233 break; 234 } 235 } 236 } 237 reboot() const238 void PowerManager::reboot() const { 239 if (daemonApp->testing()) 240 return; 241 242 for (PowerManagerBackend *backend: m_backends) { 243 if (backend->capabilities() & Capability::Reboot) { 244 backend->reboot(); 245 break; 246 } 247 } 248 } 249 suspend() const250 void PowerManager::suspend() const { 251 if (daemonApp->testing()) 252 return; 253 254 for (PowerManagerBackend *backend: m_backends) { 255 if (backend->capabilities() & Capability::Suspend) { 256 backend->suspend(); 257 break; 258 } 259 } 260 } 261 hibernate() const262 void PowerManager::hibernate() const { 263 if (daemonApp->testing()) 264 return; 265 266 for (PowerManagerBackend *backend: m_backends) { 267 if (backend->capabilities() & Capability::Hibernate) { 268 backend->hibernate(); 269 break; 270 } 271 } 272 } 273 hybridSleep() const274 void PowerManager::hybridSleep() const { 275 if (daemonApp->testing()) 276 return; 277 278 for (PowerManagerBackend *backend: m_backends) { 279 if (backend->capabilities() & Capability::HybridSleep) { 280 backend->hybridSleep(); 281 break; 282 } 283 } 284 } 285 } 286