From ce233c616d8ec5141e24d4962739040b4c99d989 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Fri, 1 Sep 2023 17:09:16 -0700 Subject: [PATCH] profiledefaults: don't automatically suspend by default if running in a virtual machine To avoid hangs in virtual environments which don't suppport suspension. https://invent.kde.org/plasma/powerdevil/-/merge_requests/230 from Natalie Clarius, rebased on 5.27.7. Signed-off-by: Adam Williamson --- daemon/powerdevilcore.cpp | 4 +++- daemon/powerdevilpowermanagement.cpp | 17 +++++++++++++++++ daemon/powerdevilpowermanagement.h | 1 + daemon/powerdevilprofilegenerator.cpp | 10 +++++----- daemon/powerdevilprofilegenerator.h | 2 +- kcmodule/profiles/EditPage.cpp | 2 ++ 6 files changed, 29 insertions(+), 7 deletions(-) diff --git a/daemon/powerdevilcore.cpp b/daemon/powerdevilcore.cpp index 0791552c..5c4f8a7d 100644 --- a/daemon/powerdevilcore.cpp +++ b/daemon/powerdevilcore.cpp @@ -24,6 +24,7 @@ #include "powerdevilaction.h" #include "powerdevilactionpool.h" #include "powerdevilpolicyagent.h" +#include "powerdevilpowermanagement.h" #include "powerdevilprofilegenerator.h" #include "powerdevil_debug.h" @@ -126,8 +127,9 @@ void Core::onBackendReady() // These are generated profiles, const bool mobile = Kirigami::TabletModeWatcher::self()->isTabletMode(); + const bool vm = PowerDevil::PowerManagement::instance()->isVirtualMachine(); - ProfileGenerator::generateProfiles(mobile, toRam, toDisk); + ProfileGenerator::generateProfiles(mobile, vm, toRam, toDisk); m_profilesConfig->reparseConfiguration(); } diff --git a/daemon/powerdevilpowermanagement.cpp b/daemon/powerdevilpowermanagement.cpp index 7b8e8d5d..ca4c9f07 100644 --- a/daemon/powerdevilpowermanagement.cpp +++ b/daemon/powerdevilpowermanagement.cpp @@ -19,6 +19,7 @@ License along with this library. If not, see . *********************************************************************/ #include "powerdevilpowermanagement.h" +#include "powerdevil_debug.h" #include #include @@ -217,6 +218,22 @@ void PowerManagement::suspendThenHibernate() QDBusConnection::sessionBus().asyncCall(message); } +bool PowerManagement::isVirtualMachine() +{ + QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.systemd1"), + QStringLiteral("/org/freedesktop/systemd1"), + QStringLiteral("org.freedesktop.DBus.Properties"), + QStringLiteral("Get")); + message.setArguments({QStringLiteral("org.freedesktop.systemd1.Manager"), QStringLiteral("Virtualization")}); + QDBusReply reply = QDBusConnection::systemBus().call(message); + if (!reply.isValid() || reply.value().variant().isNull() || reply.value().variant().toString().isNull()) { + qCWarning(POWERDEVIL) << "Failed to get property Virtualization from systemd1 DBus service:" << reply.error().message(); + return false; + } + /* on bare-metal hardware this is the empty string, otherwise an identifier such as "kvm", "vmware", etc. */ + return !reply.value().variant().toString().isEmpty(); +} + bool PowerManagement::canSuspend() const { return d->canSuspend; diff --git a/daemon/powerdevilpowermanagement.h b/daemon/powerdevilpowermanagement.h index 84c99f19..14069708 100644 --- a/daemon/powerdevilpowermanagement.h +++ b/daemon/powerdevilpowermanagement.h @@ -35,6 +35,7 @@ class Q_DECL_EXPORT PowerManagement : public QObject public: ~PowerManagement() override; + bool isVirtualMachine(); bool canSuspend() const; bool canHibernate() const; bool canHybridSuspend() const; diff --git a/daemon/powerdevilprofilegenerator.cpp b/daemon/powerdevilprofilegenerator.cpp index b3029e02..b70aa0d0 100644 --- a/daemon/powerdevilprofilegenerator.cpp +++ b/daemon/powerdevilprofilegenerator.cpp @@ -29,7 +29,7 @@ namespace PowerDevil { -void ProfileGenerator::generateProfiles(bool mobile, bool toRam, bool toDisk) +void ProfileGenerator::generateProfiles(bool mobile, bool vm, bool toRam, bool toDisk) { // Change critical action if default (hibernate) is unavailable if (!toDisk) { @@ -91,8 +91,8 @@ void ProfileGenerator::generateProfiles(bool mobile, bool toRam, bool toDisk) } // Even on AC power, suspend after a rather long period of inactivity. Energy - // is precious! - if (toRam) { + // is precious! But not on VMs. + if (toRam && !vm) { // on mobile, 7 minutes, on laptop 15 minutes auto timeout = mobile ? 420000 : 900000; KConfigGroup suspendSession(&acProfile, "SuspendSession"); @@ -124,7 +124,7 @@ void ProfileGenerator::generateProfiles(bool mobile, bool toRam, bool toDisk) } // Last but not least, we want to suspend after some inactivity - if (toRam) { + if (toRam && !vm) { // on mobile, 5 minute, on laptop 10 minutes auto timeout = mobile ? 300000 : 600000; KConfigGroup suspendSession(&batteryProfile, "SuspendSession"); @@ -164,7 +164,7 @@ void ProfileGenerator::generateProfiles(bool mobile, bool toRam, bool toDisk) // Last but not least, we want to suspend after a rather long period of inactivity // on mobile by default never suspend, if device wants to suspend, it will enable // using configuration overlay - if (toRam) { + if (toRam && !vm) { // config is in the miliseconds KConfigGroup suspendSession(&lowBatteryProfile, "SuspendSession"); suspendSession.writeEntry< uint >("idleTime", 300000); diff --git a/daemon/powerdevilprofilegenerator.h b/daemon/powerdevilprofilegenerator.h index 481caa73..6f5ffb48 100644 --- a/daemon/powerdevilprofilegenerator.h +++ b/daemon/powerdevilprofilegenerator.h @@ -36,7 +36,7 @@ namespace ProfileGenerator ToggleScreenOnOffMode = 128 }; - void generateProfiles(bool isMobile, bool toRam, bool toDisk); + void generateProfiles(bool isMobile, bool isVM, bool toRam, bool toDisk); } } diff --git a/kcmodule/profiles/EditPage.cpp b/kcmodule/profiles/EditPage.cpp index 22ed5d0e..119d818e 100644 --- a/kcmodule/profiles/EditPage.cpp +++ b/kcmodule/profiles/EditPage.cpp @@ -79,6 +79,7 @@ EditPage::EditPage(QWidget *parent, const QVariantList &args) PowerDevil::ProfileGenerator::generateProfiles( interface->isTabletMode(), + PowerDevil::PowerManagement::instance()->isVirtualMachine(), PowerDevil::PowerManagement::instance()->canSuspend(), PowerDevil::PowerManagement::instance()->canHibernate() ); @@ -198,6 +199,7 @@ void EditPage::restoreDefaultProfiles() PowerDevil::ProfileGenerator::generateProfiles( interface->isTabletMode(), + PowerDevil::PowerManagement::instance()->isVirtualMachine(), PowerDevil::PowerManagement::instance()->canSuspend(), PowerDevil::PowerManagement::instance()->canHibernate() ); -- 2.41.0