[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kde-workspace] powerdevil/daemon: implement systemd support for PowerDevil Policy Agent
From: Lukas Tinkl <lukas () kde ! org>
Date: 2012-09-21 15:48:00
Message-ID: 20120921154800.12D86A60A6 () git ! kde ! org
[Download RAW message or body]
Git commit dfb0ac5cf26df411a0374e322b741278ee8eca67 by Lukas Tinkl.
Committed on 21/09/2012 at 14:58.
Pushed by lukas into branch 'master'.
implement systemd support for PowerDevil Policy Agent
This enables PowerDevil to react on active session changes
(correct locking, screen brightness) on systems w/o ConsoleKit,
like Fedora 18
Fixes e.g. https://bugzilla.redhat.com/show_bug.cgi?id=849334
REVIEW: 106506
M +216 -54 powerdevil/daemon/powerdevilpolicyagent.cpp
M +24 -5 powerdevil/daemon/powerdevilpolicyagent.h
http://commits.kde.org/kde-workspace/dfb0ac5cf26df411a0374e322b741278ee8eca67
diff --git a/powerdevil/daemon/powerdevilpolicyagent.cpp \
b/powerdevil/daemon/powerdevilpolicyagent.cpp index 5ba595b..d971721 100644
--- a/powerdevil/daemon/powerdevilpolicyagent.cpp
+++ b/powerdevil/daemon/powerdevilpolicyagent.cpp
@@ -1,5 +1,6 @@
/***************************************************************************
* Copyright (C) 2010 by Dario Freddi <drf@kde.org> *
+ * Copyright (C) 2012 Lukáš Tinkl <ltinkl@redhat.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -20,6 +21,12 @@
#include "powerdevilpolicyagent.h"
+#include <QtCore/QCoreApplication>
+#include <QtDBus/QDBusObjectPath>
+#include <QtDBus/QDBusArgument>
+#include <QtCore/QMetaType>
+#include <QtDBus/QDBusMetaType>
+
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusPendingReply>
@@ -29,13 +36,39 @@
#include <KGlobal>
#include <KDebug>
+struct NamedDBusObjectPath
+{
+ QString name;
+ QDBusObjectPath path;
+};
+
+// Marshall the NamedDBusObjectPath data into a D-Bus argument
+QDBusArgument &operator<<(QDBusArgument &argument, const NamedDBusObjectPath \
&namedPath) +{
+ argument.beginStructure();
+ argument << namedPath.name << namedPath.path;
+ argument.endStructure();
+ return argument;
+}
+
+// Retrieve the NamedDBusObjectPath data from the D-Bus argument
+const QDBusArgument &operator>>(const QDBusArgument &argument, NamedDBusObjectPath \
&namedPath) +{
+ argument.beginStructure();
+ argument >> namedPath.name >> namedPath.path;
+ argument.endStructure();
+ return argument;
+}
+
+Q_DECLARE_METATYPE(NamedDBusObjectPath)
+
namespace PowerDevil
{
class PolicyAgentHelper
{
public:
- PolicyAgentHelper() : q(0) {}
+ PolicyAgentHelper() : q(0) { }
~PolicyAgentHelper() {
delete q;
}
@@ -55,10 +88,12 @@ PolicyAgent *PolicyAgent::instance()
PolicyAgent::PolicyAgent(QObject* parent)
: QObject(parent)
+ , m_sdAvailable(false)
, m_ckAvailable(false)
, m_sessionIsBeingInterrupted(false)
, m_lastCookie(0)
, m_busWatcher(new QDBusServiceWatcher(this))
+ , m_sdWatcher(new QDBusServiceWatcher(this))
, m_ckWatcher(new QDBusServiceWatcher(this))
{
Q_ASSERT(!s_globalPolicyAgent->q);
@@ -72,19 +107,34 @@ PolicyAgent::~PolicyAgent()
void PolicyAgent::init()
{
+ // Watch over the systemd service
+ m_sdWatcher.data()->setConnection(QDBusConnection::systemBus());
+ m_sdWatcher.data()->setWatchMode(QDBusServiceWatcher::WatchForUnregistration |
+ QDBusServiceWatcher::WatchForRegistration);
+ m_sdWatcher.data()->addWatchedService(SYSTEMD_LOGIN1_SERVICE);
+
+ connect(m_sdWatcher.data(), SIGNAL(serviceRegistered(QString)),
+ this, SLOT(onSessionHandlerRegistered(QString)));
+ connect(m_sdWatcher.data(), SIGNAL(serviceUnregistered(QString)),
+ this, SLOT(onSessionHandlerUnregistered(QString)));
+ // If it's up and running already, let's cache it
+ if (QDBusConnection::systemBus().interface()->isServiceRegistered(SYSTEMD_LOGIN1_SERVICE)) \
{ + onSessionHandlerRegistered(SYSTEMD_LOGIN1_SERVICE);
+ }
+
// Watch over the ConsoleKit service
m_ckWatcher.data()->setConnection(QDBusConnection::sessionBus());
m_ckWatcher.data()->setWatchMode(QDBusServiceWatcher::WatchForUnregistration |
QDBusServiceWatcher::WatchForRegistration);
- m_ckWatcher.data()->addWatchedService("org.freedesktop.ConsoleKit");
+ m_ckWatcher.data()->addWatchedService(CONSOLEKIT_SERVICE);
connect(m_ckWatcher.data(), SIGNAL(serviceRegistered(QString)),
- this, SLOT(onConsoleKitRegistered(QString)));
+ this, SLOT(onSessionHandlerRegistered(QString)));
connect(m_ckWatcher.data(), SIGNAL(serviceUnregistered(QString)),
- this, SLOT(onConsoleKitUnregistered(QString)));
+ this, SLOT(onSessionHandlerUnregistered(QString)));
// If it's up and running already, let's cache it
- if (QDBusConnection::systemBus().interface()->isServiceRegistered("org.freedesktop.ConsoleKit")) \
{
- onConsoleKitRegistered("org.freedesktop.ConsoleKit");
+ if (QDBusConnection::systemBus().interface()->isServiceRegistered(CONSOLEKIT_SERVICE)) \
{ + onSessionHandlerRegistered(CONSOLEKIT_SERVICE);
}
// Now set up our service watcher
@@ -95,75 +145,176 @@ void PolicyAgent::init()
this, SLOT(onServiceUnregistered(QString)));
}
-void PowerDevil::PolicyAgent::onConsoleKitRegistered(const QString& )
+QString PolicyAgent::getNamedPathProperty(const QString &path, const QString &iface, \
const QString &prop) const {
- m_ckAvailable = true;
+ QDBusMessage message = QDBusMessage::createMethodCall(SYSTEMD_LOGIN1_SERVICE, \
path, + \
QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("Get")); + message \
<< iface << prop; + QDBusMessage reply = \
QDBusConnection::systemBus().call(message); +
+ QVariantList args = reply.arguments();
+ if (!args.isEmpty()) {
+ NamedDBusObjectPath namedPath;
+ args.at(0).value<QDBusVariant>().variant().value<QDBusArgument>() >> \
namedPath; + return namedPath.path.path();
+ }
- // Otherwise, let's ask ConsoleKit
- QDBusInterface ckiface("org.freedesktop.ConsoleKit", \
"/org/freedesktop/ConsoleKit/Manager",
- "org.freedesktop.ConsoleKit.Manager", \
QDBusConnection::systemBus()); + return QString();
+}
- QDBusPendingReply<QDBusObjectPath> sessionPath = \
ckiface.asyncCall("GetCurrentSession"); +void \
PolicyAgent::onSessionHandlerRegistered(const QString & serviceName) +{
+ if (serviceName == SYSTEMD_LOGIN1_SERVICE) {
+ m_sdAvailable = true;
- sessionPath.waitForFinished();
+ qRegisterMetaType<NamedDBusObjectPath>();
+ qDBusRegisterMetaType<NamedDBusObjectPath>();
- if (!sessionPath.isValid() || sessionPath.value().path().isEmpty()) {
- kDebug() << "The session is not registered with ck";
- m_ckAvailable = false;
- return;
- }
+ // get the current session
+ QDBusInterface managerIface(SYSTEMD_LOGIN1_SERVICE, SYSTEMD_LOGIN1_PATH, \
SYSTEMD_LOGIN1_MANAGER_IFACE, QDBusConnection::systemBus()); + \
QDBusPendingReply<QDBusObjectPath> session = \
managerIface.asyncCall(QLatin1String("GetSessionByPID"), (quint32) \
QCoreApplication::applicationPid()); + session.waitForFinished();
- m_ckSessionInterface = new QDBusInterface("org.freedesktop.ConsoleKit", \
sessionPath.value().path(),
- "org.freedesktop.ConsoleKit.Session", \
QDBusConnection::systemBus()); + if (!session.isValid()) {
+ kDebug() << "The session is not registered with systemd";
+ m_sdAvailable = false;
+ return;
+ }
- if (!m_ckSessionInterface.data()->isValid()) {
- // As above
- kDebug() << "Can't contact iface";
- m_ckAvailable = false;
- return;
- }
+ QString sessionPath = session.value().path();
+ kDebug() << "Session path:" << sessionPath;
+
+ m_sdSessionInterface = new QDBusInterface(SYSTEMD_LOGIN1_SERVICE, \
sessionPath, + \
SYSTEMD_LOGIN1_SESSION_IFACE, QDBusConnection::systemBus(), this); + if \
(!m_sdSessionInterface.data()->isValid()) { + // As above
+ kDebug() << "Can't contact session iface";
+ m_sdAvailable = false;
+ delete m_sdSessionInterface.data();
+ return;
+ }
- // Now let's obtain the seat
- QDBusPendingReply< QDBusObjectPath > seatPath = \
m_ckSessionInterface.data()->asyncCall("GetSeatId");
- seatPath.waitForFinished();
- if (!sessionPath.isValid() || sessionPath.value().path().isEmpty()) {
- kDebug() << "Unable to associate ck session with a seat";
- m_ckAvailable = false;
- return;
- }
+ // now let's obtain the seat
+ QString seatPath = getNamedPathProperty(sessionPath, \
SYSTEMD_LOGIN1_SESSION_IFACE, "Seat");
- if (!QDBusConnection::systemBus().connect("org.freedesktop.ConsoleKit", \
seatPath.value().path(),
- "org.freedesktop.ConsoleKit.Seat", \
"ActiveSessionChanged",
- this, \
SLOT(onConsoleKitActiveSessionChanged(QString)))) {
- kDebug() << "Unable to connect to ActiveSessionChanged";
- m_ckAvailable = false;
- return;
- }
+ if (seatPath.isEmpty() || seatPath == "/") {
+ kDebug() << "Unable to associate systemd session with a seat" << \
seatPath; + m_sdAvailable = false;
+ return;
+ }
- // Force triggering of active session changed
- QDBusMessage call = QDBusMessage::createMethodCall("org.freedesktop.ConsoleKit", \
seatPath.value().path(),
- \
"org.freedesktop.ConsoleKit.Seat", "GetActiveSession");
- QDBusPendingReply< QDBusObjectPath > activeSession = \
QDBusConnection::systemBus().asyncCall(call);
- activeSession.waitForFinished();
+ // get the current seat
+ m_sdSeatInterface = new QDBusInterface(SYSTEMD_LOGIN1_SERVICE, seatPath,
+ SYSTEMD_LOGIN1_SEAT_IFACE, \
QDBusConnection::systemBus(), this);
- onConsoleKitActiveSessionChanged(activeSession.value().path());
+ if (!m_sdSeatInterface.data()->isValid()) {
+ // As above
+ kDebug() << "Can't contact seat iface";
+ m_sdAvailable = false;
+ delete m_sdSeatInterface.data();
+ return;
+ }
- kDebug() << "ConsoleKit support initialized";
+ // finally get the active session path and watch for its changes
+ m_activeSessionPath = getNamedPathProperty(seatPath, \
SYSTEMD_LOGIN1_SEAT_IFACE, "ActiveSession"); +
+ kDebug() << "ACTIVE SESSION PATH:" << m_activeSessionPath;
+ QDBusConnection::systemBus().connect(SYSTEMD_LOGIN1_SERVICE, seatPath, \
"org.freedesktop.DBus.Properties", "PropertiesChanged", this, + \
SLOT(onActiveSessionChanged(QString,QVariantMap,QStringList))); +
+ onActiveSessionChanged(m_activeSessionPath);
+
+ kDebug() << "systemd support initialized";
+ } else if (serviceName == CONSOLEKIT_SERVICE) {
+ m_ckAvailable = true;
+
+ // Otherwise, let's ask ConsoleKit
+ QDBusInterface ckiface(CONSOLEKIT_SERVICE, \
"/org/freedesktop/ConsoleKit/Manager", + \
"org.freedesktop.ConsoleKit.Manager", QDBusConnection::systemBus()); +
+ QDBusPendingReply<QDBusObjectPath> sessionPath = \
ckiface.asyncCall("GetCurrentSession"); +
+ sessionPath.waitForFinished();
+
+ if (!sessionPath.isValid() || sessionPath.value().path().isEmpty()) {
+ kDebug() << "The session is not registered with ck";
+ m_ckAvailable = false;
+ return;
+ }
+
+ m_ckSessionInterface = new QDBusInterface(CONSOLEKIT_SERVICE, \
sessionPath.value().path(), + \
"org.freedesktop.ConsoleKit.Session", QDBusConnection::systemBus()); +
+ if (!m_ckSessionInterface.data()->isValid()) {
+ // As above
+ kDebug() << "Can't contact iface";
+ m_ckAvailable = false;
+ return;
+ }
+
+ // Now let's obtain the seat
+ QDBusPendingReply< QDBusObjectPath > seatPath = \
m_ckSessionInterface.data()->asyncCall("GetSeatId"); + \
seatPath.waitForFinished(); +
+ if (!seatPath.isValid() || seatPath.value().path().isEmpty()) {
+ kDebug() << "Unable to associate ck session with a seat";
+ m_ckAvailable = false;
+ return;
+ }
+
+ if (!QDBusConnection::systemBus().connect(CONSOLEKIT_SERVICE, \
seatPath.value().path(), + \
"org.freedesktop.ConsoleKit.Seat", "ActiveSessionChanged", + \
this, SLOT(onActiveSessionChanged(QString)))) { + kDebug() << "Unable to \
connect to ActiveSessionChanged"; + m_ckAvailable = false;
+ return;
+ }
+
+ // Force triggering of active session changed
+ QDBusMessage call = QDBusMessage::createMethodCall(CONSOLEKIT_SERVICE, \
seatPath.value().path(), + \
"org.freedesktop.ConsoleKit.Seat", "GetActiveSession"); + QDBusPendingReply< \
QDBusObjectPath > activeSession = QDBusConnection::systemBus().asyncCall(call); + \
activeSession.waitForFinished(); +
+ onActiveSessionChanged(activeSession.value().path());
+
+ kDebug() << "ConsoleKit support initialized";
+ }
+ else
+ kdWarning() << "Unhandled service registered:" << serviceName;
}
-void PowerDevil::PolicyAgent::onConsoleKitUnregistered(const QString& )
+void PolicyAgent::onSessionHandlerUnregistered(const QString & serviceName)
{
- m_ckAvailable = false;
- m_ckSessionInterface.data()->deleteLater();
+ if (serviceName == SYSTEMD_LOGIN1_SERVICE) {
+ m_sdAvailable = false;
+ delete m_sdSessionInterface.data();
+ }
+ else if (serviceName == CONSOLEKIT_SERVICE) {
+ m_ckAvailable = false;
+ delete m_ckSessionInterface.data();
+ }
}
-void PolicyAgent::onConsoleKitActiveSessionChanged(const QString& activeSession)
+void PolicyAgent::onActiveSessionChanged(const QString & ifaceName, const \
QVariantMap & changedProps, const QStringList & invalidatedProps) {
- if (activeSession.isEmpty()) {
+ const QString key = QLatin1String("ActiveSession");
+
+ if (ifaceName == SYSTEMD_LOGIN1_SEAT_IFACE && (changedProps.keys().contains(key) \
|| invalidatedProps.contains(key))) { + m_activeSessionPath = \
getNamedPathProperty(m_sdSeatInterface.data()->path(), SYSTEMD_LOGIN1_SEAT_IFACE, \
key); + kDebug() << "ACTIVE SESSION PATH CHANGED:" << m_activeSessionPath;
+ onActiveSessionChanged(m_activeSessionPath);
+ }
+}
+
+void PolicyAgent::onActiveSessionChanged(const QString& activeSession)
+{
+ if (activeSession.isEmpty() || activeSession == "/") {
kDebug() << "Switched to inactive session - leaving unchanged";
return;
- } else if (activeSession == m_ckSessionInterface.data()->path()) {
+ } else if ((!m_sdSessionInterface.isNull() && activeSession == \
m_sdSessionInterface.data()->path()) || + \
(!m_ckSessionInterface.isNull() && activeSession == \
m_ckSessionInterface.data()->path())) { kDebug() << "Current session is now active";
m_wasLastActiveSession = true;
} else {
@@ -201,6 +352,17 @@ PolicyAgent::RequiredPolicies PolicyAgent::unavailablePolicies()
PolicyAgent::RequiredPolicies \
PolicyAgent::requirePolicyCheck(PolicyAgent::RequiredPolicies policies) {
+ if (!m_sdAvailable) {
+ // No way to determine if we are on the current session, simply suppose we \
are + kDebug() << "Can't contact systemd";
+ } else if (!m_sdSessionInterface.isNull()) {
+ bool isActive = m_sdSessionInterface.data()->property("Active").toBool();
+
+ if (!isActive && !m_wasLastActiveSession && policies != InterruptSession) {
+ return policies;
+ }
+ }
+
if (!m_ckAvailable) {
// No way to determine if we are on the current session, simply suppose we \
are kDebug() << "Can't contact ck";
diff --git a/powerdevil/daemon/powerdevilpolicyagent.h \
b/powerdevil/daemon/powerdevilpolicyagent.h index f637f1e..6001846 100644
--- a/powerdevil/daemon/powerdevilpolicyagent.h
+++ b/powerdevil/daemon/powerdevilpolicyagent.h
@@ -1,5 +1,6 @@
/***************************************************************************
* Copyright (C) 2010 by Dario Freddi <drf@kde.org> *
+ * Copyright (C) 2012 Lukáš Tinkl <ltinkl@redhat.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -32,6 +33,15 @@
class QDBusServiceWatcher;
class QDBusInterface;
+#define SYSTEMD_LOGIN1_SERVICE "org.freedesktop.login1"
+#define SYSTEMD_LOGIN1_PATH "/org/freedesktop/login1"
+#define SYSTEMD_LOGIN1_MANAGER_IFACE "org.freedesktop.login1.Manager"
+#define SYSTEMD_LOGIN1_SESSION_IFACE "org.freedesktop.login1.Session"
+#define SYSTEMD_LOGIN1_SEAT_IFACE "org.freedesktop.login1.Seat"
+
+#define CONSOLEKIT_SERVICE "org.freedesktop.ConsoleKit"
+
+
namespace PowerDevil
{
@@ -69,15 +79,15 @@ public Q_SLOTS:
void ReleaseInhibition(uint cookie);
void releaseAllInhibitions();
-
Q_SIGNALS:
void unavailablePoliciesChanged(PowerDevil::PolicyAgent::RequiredPolicies \
newpolicies);
private Q_SLOTS:
- void onServiceUnregistered(const QString &serviceName);
- void onConsoleKitRegistered(const QString&);
- void onConsoleKitUnregistered(const QString&);
- void onConsoleKitActiveSessionChanged(const QString &activeSession);
+ void onServiceUnregistered(const QString & serviceName);
+ void onSessionHandlerRegistered(const QString & serviceName);
+ void onSessionHandlerUnregistered(const QString & serviceName);
+ void onActiveSessionChanged(const QString & ifaceName, const QVariantMap & \
changedProps, const QStringList & invalidatedProps); + void \
onActiveSessionChanged(const QString &activeSession);
private:
explicit PolicyAgent(QObject* parent = 0);
@@ -92,6 +102,14 @@ private:
uint addInhibitionWithExplicitDBusService(uint types, const QString &appName,
const QString &reason, const QString \
&service);
+ // systemd support
+ QString getNamedPathProperty(const QString & path, const QString & iface, const \
QString & prop) const; + bool m_sdAvailable;
+ QString m_activeSessionPath;
+ QWeakPointer< QDBusInterface > m_sdSessionInterface;
+ QWeakPointer< QDBusInterface > m_sdSeatInterface;
+
+ // ConsoleKit support
bool m_ckAvailable;
QWeakPointer< QDBusInterface > m_ckSessionInterface;
QWeakPointer< QDBusInterface > m_ckSeatInterface;
@@ -104,6 +122,7 @@ private:
uint m_lastCookie;
QWeakPointer< QDBusServiceWatcher > m_busWatcher;
+ QWeakPointer< QDBusServiceWatcher > m_sdWatcher;
QWeakPointer< QDBusServiceWatcher > m_ckWatcher;
bool m_wasLastActiveSession;
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic