From 286299b70a23608b99080f7cd9fdf8ae01d71db0 Mon Sep 17 00:00:00 2001 From: xionglinlin Date: Sat, 16 May 2026 13:49:12 +0800 Subject: [PATCH] feat: recover power mode after sleep/shutdown/reboot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When performing shutdown, reboot, hibernate or suspend operations, switch to performance mode before the operation, and restore the user's configured power mode upon wake or next startup. This ensures smooth transitions and optimal performance during these critical operations. Key changes: 1. Add `setTlpMode()` helper function to set power mode via D-Bus 2. Add `recoverySystemPowerMode()` to restore user's configured power mode after wake 3. Call `setTlpMode(Performance)` before shutdown, reboot, hibernate, and suspend 4. Connect to `PrepareForSleep` signal to restore mode after sleep wake 5. On startup, schedule recovery of power mode via timer Log: Optimized power management behavior during system suspend/ hibernate/reboot/shutdown Influence: 1. Test shutdown: verify system switches to performance mode before shutdown 2. Test reboot: verify performance mode is set before reboot 3. Test hibernate: verify performance mode is set before hibernation 4. Test suspend: verify performance mode is set before suspend 5. Test wake from sleep: verify user's original power mode is restored 6. Test startup: verify power mode is restored to user's configuration 7. Test with/without battery: verify low battery mode handling on battery ≤20% 8. Verify D-Bus communication with org.deepin.dde.Power1 service 9. Test error handling when D-Bus calls fail feat: 恢复休眠/关机/重启后的电源模式 在执行关机、重启、休眠或挂起操作前,先将系统切换到高性能模式,操作完成后 (唤醒或下次启动)再恢复为用户之前配置的电源模式。这确保了这些关键操作期 间的流畅过渡和最佳性能。 主要变更: 1. 添加 `setTlpMode()` 辅助函数,通过 D-Bus 设置电源模式 2. 添加 `recoverySystemPowerMode()` 恢复用户配置的电源模式 3. 在关机、重启、休眠和挂起前调用 `setTlpMode(Performance)` 4. 连接 `PrepareForSleep` 信号,在睡眠唤醒后恢复模式 5. 在启动时通过定时器调度恢复电源模式 Log: 优化系统挂起/休眠/重启/关机时的电源管理行为 Influence: 1. 测试关机:验证关机前是否切换为高性能模式 2. 测试重启:验证重启前是否设置为高性能模式 3. 测试休眠:验证休眠前是否设置为高性能模式 4. 测试挂起:验证挂起前是否设置为高性能模式 5. 测试从睡眠唤醒:验证是否恢复用户原始电源模式 6. 测试启动:验证电源模式是否恢复为用户配置 7. 测试有/无电池情况:验证电池电量≤20%时的低电量模式处理 8. 验证与 org.deepin.dde.Power1 服务的 D-Bus 通信 9. 测试 D-Bus 调用失败时的错误处理 PMS: TASK-389737 Change-Id: I30122c303b2b61a4912a554ccfb0d75dce3747a1 --- src/dde-session/impl/sessionmanager.cpp | 84 +++++++++++++++++++++++++ src/dde-session/impl/sessionmanager.h | 2 + 2 files changed, 86 insertions(+) diff --git a/src/dde-session/impl/sessionmanager.cpp b/src/dde-session/impl/sessionmanager.cpp index 9b50d3e..964abc0 100644 --- a/src/dde-session/impl/sessionmanager.cpp +++ b/src/dde-session/impl/sessionmanager.cpp @@ -19,11 +19,16 @@ #include #include #include +#include #include #include #include +static const QString Performance = QStringLiteral("performance"); +static const QString PowerSave = QStringLiteral("powersave"); +static const QString LowBattery = QStringLiteral("lowBattery"); + #define MASK_SERVICE(service) \ {\ auto reply = m_systemd1ManagerInter->MaskUnitFiles(QStringList() << service, true, true);\ @@ -124,6 +129,14 @@ void SessionManager::initConnections() const bool active = m_login1SessionInter->active(); Q_UNUSED(active) + connect(m_login1ManagerInter, &org::freedesktop::login1::Manager::PrepareForSleep, [=](bool sleep) { + qDebug() << "system is preparing for sleep: " << sleep; + if (!sleep) { + // 唤醒后恢复之前的电源模式 + recoverySystemPowerMode(); + } + }); + connect(m_login1SessionInter, &org::freedesktop::login1::Session::ActiveChanged, [=](bool active) { qDebug() << "session active status changed to:" << active; if (active) { @@ -404,6 +417,7 @@ bool SessionManager::Register(const QString &id) void SessionManager::RequestHibernate() { + setTlpMode(Performance); QDBusPendingReply<> reply = m_login1ManagerInter->Hibernate(false); if (reply.isError()) { qWarning() << "failed to hibernate, error: " << reply.error().name(); @@ -447,11 +461,13 @@ void SessionManager::RequestLogout() void SessionManager::RequestReboot() { + setTlpMode(Performance); reboot(true); } void SessionManager::RequestShutdown() { + setTlpMode(Performance); shutdown(true); } @@ -463,6 +479,8 @@ void SessionManager::RequestSuspend() return; } + setTlpMode(Performance); + // 使用窗管接口进行黑屏处理 if (Dconf::SetValue("com.deepin.dde.startdde", "", "quick-black-screen", QVariant(false))) { QDBusInterface inter("org.kde.KWin", "/BlackScreen", "org.kde.kwin.BlackScreen", QDBusConnection::sessionBus(), this); @@ -546,6 +564,10 @@ void SessionManager::init() if (!Utils::IS_WAYLAND_DISPLAY) { watchXConnection(); } + + QTimer::singleShot(0, this, [this] { + recoverySystemPowerMode(); + }); qInfo() << "session manager init finished"; } @@ -860,6 +882,68 @@ void SessionManager::handleOSSignal() signal(SIGSEGV, sig_crash); } +void SessionManager::setTlpMode(const QString &mode) +{ + qInfo() << "setTlpMode mode:" << mode; + QDBusInterface inter("org.deepin.dde.Power1", "/org/deepin/dde/Power1", "org.deepin.dde.Power1", QDBusConnection::systemBus()); + QDBusPendingReply<> reply = inter.asyncCall("SetTlpMode", mode); + Q_UNUSED(reply) +} + +void SessionManager::recoverySystemPowerMode() +{ + qInfo() << "recoverySystemPowerMode"; + QDBusInterface inter("org.deepin.dde.Power1", "/org/deepin/dde/Power1", + "org.freedesktop.DBus.Properties", QDBusConnection::systemBus()); + + // 获取 TlpMode + QDBusMessage tlpMsg = inter.call("Get", "org.deepin.dde.Power1", "TlpMode"); + QString tlpMode; + if (tlpMsg.type() == QDBusMessage::ReplyMessage) { + tlpMode = tlpMsg.arguments().value(0).value().variant().toString(); + } else { + qWarning() << "Get DBus property TlpMode failed:" << tlpMsg.errorMessage(); + return; + } + + // 获取 Mode + QDBusMessage modeMsg = inter.call("Get", "org.deepin.dde.Power1", "Mode"); + QString mode; + if (modeMsg.type() == QDBusMessage::ReplyMessage) { + mode = modeMsg.arguments().value(0).value().variant().toString(); + } else { + qWarning() << "Get DBus property Mode failed:" << modeMsg.errorMessage(); + return; + } + + qInfo() << "DBus property of TlpMode:" << tlpMode << ", Mode:" << mode; + + if (mode == tlpMode) + return; + + // 如果目标是节能模式,检查电池状态决定是否需要切换到低电量模式 + if (mode == PowerSave) { + QDBusMessage batteryMsg = inter.call("Get", "org.deepin.dde.Power1", "HasBattery"); + if (batteryMsg.type() == QDBusMessage::ReplyMessage) { + bool hasBattery = batteryMsg.arguments().value(0).value().variant().toBool(); + if (!hasBattery) { + setTlpMode(mode); + return; + } + + QDBusMessage capacityMsg = inter.call("Get", "org.deepin.dde.Power1", "BatteryCapacity"); + if (capacityMsg.type() == QDBusMessage::ReplyMessage) { + double batteryCapacity = capacityMsg.arguments().value(0).value().variant().toDouble(); + if (batteryCapacity <= 20.0) { + mode = LowBattery; + } + } + } + } + + setTlpMode(mode); +} + void SessionManager::shutdown(bool force) { prepareShutdown(force); diff --git a/src/dde-session/impl/sessionmanager.h b/src/dde-session/impl/sessionmanager.h index 5b2e12e..4ca948e 100644 --- a/src/dde-session/impl/sessionmanager.h +++ b/src/dde-session/impl/sessionmanager.h @@ -103,6 +103,8 @@ public Q_SLOTS: void watchXConnection(); void shutdown(bool force); + void setTlpMode(const QString &mode); + void recoverySystemPowerMode(); void reboot(bool force); // 主动触发DBus的PropertiesChanged信息,否则调用方无法监听属性变化