From c55a0e0c777a96e43d54e3f1a44b62b2bf544aa3 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 | 87 +++++++++++++++++++++++++ src/dde-session/impl/sessionmanager.h | 2 + 2 files changed, 89 insertions(+) diff --git a/src/dde-session/impl/sessionmanager.cpp b/src/dde-session/impl/sessionmanager.cpp index ef70266..a0b3edc 100644 --- a/src/dde-session/impl/sessionmanager.cpp +++ b/src/dde-session/impl/sessionmanager.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,10 @@ using namespace Dtk::Core; +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);\ @@ -126,6 +131,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) { @@ -396,6 +409,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(); @@ -439,11 +453,13 @@ void SessionManager::RequestLogout() void SessionManager::RequestReboot() { + setTlpMode(Performance); reboot(true); } void SessionManager::RequestShutdown() { + setTlpMode(Performance); shutdown(true); } @@ -455,6 +471,8 @@ void SessionManager::RequestSuspend() return; } + setTlpMode(Performance); + QDBusPendingReply<> reply = m_login1ManagerInter->Suspend(false); if (reply.isError()) { qWarning() << "failed to suspend, error:" << reply.error().name(); @@ -530,6 +548,10 @@ void SessionManager::init() if (!Utils::IS_WAYLAND_DISPLAY) { watchXConnection(); } + + QTimer::singleShot(0, this, [this] { + recoverySystemPowerMode(); + }); qInfo() << "session manager init finished"; } @@ -845,6 +867,71 @@ 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()); + inter.setTimeout(3000); // 3秒超时,防止关机流程被阻塞 + QDBusMessage reply = inter.call("SetTlpMode", mode); + if (reply.type() == QDBusMessage::ErrorMessage) { + qWarning() << "SetTlpMode failed:" << reply.errorMessage(); + } +} + +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 db3c9db..d06d27f 100644 --- a/src/dde-session/impl/sessionmanager.h +++ b/src/dde-session/impl/sessionmanager.h @@ -102,6 +102,8 @@ public Q_SLOTS: void watchXConnection(); void shutdown(bool force); + void setTlpMode(const QString &mode); + void recoverySystemPowerMode(); void reboot(bool force); // 主动触发DBus的PropertiesChanged信息,否则调用方无法监听属性变化