feat: recover power mode after sleep/shutdown/reboot#208
Conversation
There was a problem hiding this comment.
Sorry @xionglinlin, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
mhduiy
left a comment
There was a problem hiding this comment.
Code Review: PR #208
功能目标明确:在关机/重启/休眠/挂起前切换高性能模式,唤醒/启动后恢复用户配置。以下是具体问题:
🔴 需要修复的问题
1. sessionmanager.cpp - setTlpMode 异步调用导致竞态
void SessionManager::setTlpMode(const QString &mode)
{
QDBusInterface inter(...);
QDBusPendingReply<> reply = inter.asyncCall("SetTlpMode", mode);
Q_UNUSED(reply)
}
void SessionManager::RequestShutdown()
{
setTlpMode(Performance); // 异步,不等待结果
shutdown(true); // 立即执行关机
}问题:setTlpMode 是异步调用,RequestShutdown/RequestReboot/RequestSuspend 不等待 TLP 模式设置完成就立即执行关机/重启/挂起。在实际场景中,关机流程可能在 TLP 模式切换完成之前就已经终止了 DDE 服务,导致高性能模式设置失败——整个功能的核心目标可能无法达成。
建议:使用 QDBusPendingCallWatcher 等待调用完成后再执行关机流程,或使用同步 call() 方式(考虑到这是关机前的一次性操作,短暂阻塞可接受)。
2. sessionmanager.cpp - recoverySystemPowerMode 同步 D-Bus 调用过多
QDBusMessage tlpMsg = inter.call("Get", "org.deepin.dde.Power1", "TlpMode"); // 同步
QDBusMessage modeMsg = inter.call("Get", "org.deepin.dde.Power1", "Mode"); // 同步
QDBusMessage batteryMsg = inter.call("Get", ..., "HasBattery"); // 同步
QDBusMessage capacityMsg = inter.call("Get", ..., "BatteryCapacity"); // 同步问题:最多 4 次同步 D-Bus 调用,每次调用可能耗时数十毫秒到数秒。在启动路径 (init()) 中调用时,会拖慢启动速度。在 PrepareForSleep(false) 唤醒回调中调用时,D-Bus 服务可能尚未完全就绪。
建议:
- 启动时:考虑延迟恢复或使用
QTimer::singleShot增加重试 - 唤醒时:先检查 D-Bus 服务是否可用,失败后延迟重试
3. sessionmanager.cpp - 电源模式字符串硬编码
static const QString Performance = QStringLiteral("performance");
static const QString PowerSave = QStringLiteral("powersave");
static const QString LowBattery = QStringLiteral("lowBattery");问题:这些字符串必须与 dde-daemon 中的电源模式常量保持一致。如果 dde-daemon 修改了这些值,此处会静默失败。
建议:考虑通过 D-Bus 接口查询可用的模式列表,或在注释中明确标注依赖关系。LowBattery 是 dde-daemon 内部使用的值,是否应该通过 TlpMode 直接使用 dde-daemon 暴露的 Mode 属性而非自己做 battery 判断?
4. sessionmanager.cpp:567 - 启动时的 recoverySystemPowerMode 时机问题
QTimer::singleShot(0, this, [this] { recoverySystemPowerMode(); });问题:QTimer::singleShot(0) 只保证在当前事件循环迭代完成后执行,但不能保证 org.deepin.dde.Power1 的 D-Bus 服务已经就绪。在冷启动场景下,系统服务可能尚未注册到 D-Bus。
建议:添加重试机制,例如失败后每秒重试,最多 3-5 次。
🟡 建议改进
5. 电池电量阈值硬编码
if (batteryCapacity <= 20.0) {
mode = LowBattery;
}建议:提取为常量,并添加注释说明此阈值应与 dde-daemon 中的低电量阈值保持一致。
6. recoverySystemPowerMode 缺少成功日志
建议:在函数末尾添加 qInfo() << "Recovered power mode to:" << mode;,方便排查问题。
7. 行尾有多余空格
QTimer::singleShot(0, this, [this] { 建议:清理行尾空格。
8. PrepareForSleep 信号连接位置
connect(m_login1ManagerInter, &org::freedesktop::login1::Manager::PrepareForSleep, [=](bool sleep) {建议:此 lambda 捕获了 this(通过 [=]),但这里应该使用 [this] 显式捕获,避免意外捕获其他变量。虽然当前没有其他局部变量,但 [=] 是不良实践。
🟢 整体评价
- 功能设计思路正确:操作前切高性能,唤醒后恢复
PrepareForSleep信号的使用是正确的唤醒恢复方案- 代码结构清晰,新增的两个方法职责单一
- 核心风险:异步调用导致 TLP 模式可能来不及设置就关机(第 1 点),建议优先修复
|
TAG Bot New tag: 2.0.25 |
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
deepin pr auto review我对这段代码进行了审查,以下是关于语法逻辑、代码质量、代码性能和代码安全的改进建议: 1. 语法逻辑优点:
改进建议:
2. 代码质量优点:
改进建议:
3. 代码性能优点:
改进建议:
4. 代码安全优点:
改进建议:
具体改进建议
static const QString POWER_SERVICE = "org.deepin.dde.Power1";
static const QString POWER_PATH = "/org/deepin/dde/Power1";
static const QString POWER_INTERFACE = "org.deepin.dde.Power1";
static const QString PROPERTIES_INTERFACE = "org.freedesktop.DBus.Properties";
void SessionManager::recoverySystemPowerMode()
{
qInfo() << "recoverySystemPowerMode";
QString currentMode = getCurrentPowerMode();
QString targetMode = determineTargetPowerMode(currentMode);
if (currentMode != targetMode) {
setTlpMode(targetMode);
}
}
QString SessionManager::getCurrentPowerMode()
{
// 获取当前电源模式的实现
}
QString SessionManager::determineTargetPowerMode(const QString ¤tMode)
{
// 根据当前模式和系统状态确定目标模式的实现
}
void SessionManager::setTlpMode(const QString &mode, int maxRetries = 3)
{
qInfo() << "setTlpMode mode:" << mode;
QDBusInterface inter(POWER_SERVICE, POWER_PATH, POWER_INTERFACE, QDBusConnection::systemBus());
inter.setTimeout(3000);
int retryCount = 0;
while (retryCount < maxRetries) {
QDBusMessage reply = inter.call("SetTlpMode", mode);
if (reply.type() != QDBusMessage::ErrorMessage) {
return;
}
qWarning() << "SetTlpMode failed (attempt" << retryCount + 1 << "):" << reply.errorMessage();
retryCount++;
QThread::msleep(1000); // 等待1秒后重试
}
qCritical() << "Failed to set TlpMode after" << maxRetries << "attempts";
}
void SessionManager::setTlpMode(const QString &mode)
{
static const QStringList validModes = {Performance, PowerSave, LowBattery};
if (!validModes.contains(mode)) {
qWarning() << "Invalid TLP mode:" << mode;
return;
}
// 原有实现...
}这些建议可以提高代码的健壮性、可维护性和性能,同时增强错误处理能力。 |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: mhduiy, xionglinlin The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
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:
setTlpMode()helper function to set power mode via D-BusrecoverySystemPowerMode()to restore user's configured power mode after wakesetTlpMode(Performance)before shutdown, reboot, hibernate, and suspendPrepareForSleepsignal to restore mode after sleep wakeLog: Optimized power management behavior during system suspend/ hibernate/reboot/shutdown
Influence:
feat: 恢复休眠/关机/重启后的电源模式
在执行关机、重启、休眠或挂起操作前,先将系统切换到高性能模式,操作完成后
(唤醒或下次启动)再恢复为用户之前配置的电源模式。这确保了这些关键操作期
间的流畅过渡和最佳性能。
主要变更:
setTlpMode()辅助函数,通过 D-Bus 设置电源模式recoverySystemPowerMode()恢复用户配置的电源模式setTlpMode(Performance)PrepareForSleep信号,在睡眠唤醒后恢复模式Log: 优化系统挂起/休眠/重启/关机时的电源管理行为
Influence:
PMS: TASK-389737
Change-Id: I30122c303b2b61a4912a554ccfb0d75dce3747a1