Skip to content

feat: add short idle and TLP mode support#1111

Open
xionglinlin wants to merge 1 commit into
linuxdeepin:masterfrom
xionglinlin:feat/short-idle-tlp
Open

feat: add short idle and TLP mode support#1111
xionglinlin wants to merge 1 commit into
linuxdeepin:masterfrom
xionglinlin:feat/short-idle-tlp

Conversation

@xionglinlin
Copy link
Copy Markdown
Contributor

  1. Add short idle state management with kernel file writing via dde- system-daemon
  2. Add TLP mode setting interface in system power1
  3. Implement short idle delay configuration and power saving plan
  4. Add third-party application detection to control short idle entry
  5. Add screen state from DPMS off/on events
  6. Add DSG configuration for idle paths, delays, and blacklists

Log: Added short idle state management and TLP mode configuration for power saving optimization

Influence:

  1. Test short idle entry and exit with various delay configurations
  2. Verify TLP mode switching via D-Bus interface
  3. Test third-party application detection prevents short idle entry
  4. Verify short idle blacklist and whitelist application behavior
  5. Test screen state synchronization with DPMS events
  6. Verify kernel file writing for idle and screen states
  7. Test DSG configuration changes are properly applied

feat: 添加短idle和TLP模式支持

  1. 通过dde-system-daemon添加短idle状态管理及内核文件写入功能
  2. 在系统电源管理中新增TLP模式设置接口
  3. 实现短idle延迟配置和节能计划管理
  4. 添加第三方应用检测机制以控制短idle进入
  5. 从DPMS关闭/打开事件同步屏幕状态
  6. 新增DSG配置项:空闲路径、延迟时间和黑名单

Log: 新增短idle状态管理和TLP模式配置,优化节能策略

Influence:

  1. 测试不同延迟配置下的短idle进入和退出
  2. 通过D-Bus接口验证TLP模式切换功能
  3. 测试第三方应用运行阻止短idle进入的逻辑
  4. 验证短idle黑名单和白名单应用的行为
  5. 测试屏幕状态与DPMS事件的同步
  6. 验证空闲和屏幕状态的内核文件写入
  7. 测试DSG配置变更的正确应用

PMS: TASK-389737
Change-Id: Ia3572bf438ff45f8c67e7f354f991fd6535f7775

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @xionglinlin, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: xionglinlin

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Copy link
Copy Markdown
Contributor

@mhduiy mhduiy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: PR #1111

整体功能完整,涵盖了短 idle 管理、TLP 模式、第三方应用检测、DSG 配置等。以下按严重程度分级列出问题和建议:


🔴 需要修复的问题

1. system/power1/manager.go - setTlpMode 未更新 m.TlpMode 字段

func (m *Manager) setTlpMode(mode string) error {
    if m.TlpMode == mode {
        return errors.New("repeat set tlp mode")
    }
    // ... 设置 DSPCState
    return nil
}

问题m.TlpMode 从未被赋值为新的 mode,导致"重复设置"的保护逻辑完全无效,每次都会重新执行 setDSPCState
建议:在设置成功后更新 m.TlpMode = mode

2. session/power1/power_save_plan.go - Map 并发读写竞态

systemApplicationsMapshortIdleBlackListApplicationsMap 在以下场景存在竞态:

  • initDsgConfigValueChanged 回调中写 map(在 signalLoop goroutine 中)
  • isThirdPartyAppRunning 中读 map(在 metaTask 执行中)
  • 没有任何 mutex 保护,可能触发 concurrent map read and map write panic。
    建议:使用 sync.RWMutex 保护这两个 map 的读写,或者使用 sync.Map

3. bin/dde-system-daemon/main.go - _daemon.service 重复赋值

_daemon = &Daemon{
    service:             service,
    // ...
}
_daemon.getDsgValue()  // getDsgValue 中创建了自己的 configManager 连接
_daemon.service = service  // ← 重复赋值,无意义

建议:删除第 121 行的 _daemon.service = service

4. system/power1/manager.go - doSetMode 中的延时 hack

time.AfterFunc(500*time.Millisecond, func() {
    err := m.setTlpMode(ddePowerSave)
    // ...
})

问题:用固定 500ms 延时来规避 deepin-power-control 连续调用失败的问题,这是治标不治本的方案。在高负载或低性能设备上 500ms 可能不够,在正常设备上又浪费时间。
建议:修复 deepin-power-control 连续调用的根本问题,或至少增加重试逻辑 + 上限超时。


🟡 建议改进

5. bin/dde-system-daemon/power.go - 使用已废弃的 ioutil

content, err := ioutil.ReadFile(file)
err = ioutil.WriteFile(file, []byte(newContent), 0644)

建议:替换为 os.ReadFileos.WriteFileioutil 自 Go 1.16 起已废弃)。

6. bin/dde-system-daemon/power.go - isStrInList 重复造轮子

func isStrInList(item string, items []string) bool {

建议:如果项目 Go 版本 ≥ 1.21,使用 slices.Contains(item, items) 替代。

7. bin/dde-system-daemon/power.go - setStateshortIdleState 零值问题

shortIdleState, err := d.systemPower.ShortIdleState().Get(0)
if err != nil {
    logger.Warning("Get systemPower.ShortIdleState err :", err)
}
// 如果出错,shortIdleState 为零值 false
if shortIdleState == state {
    return errors.New("Short idle state not exchange.")
}

问题:D-Bus 调用失败时 shortIdleState 默认为 false,如果传入的 state 也是 false,会误判为"状态未变化"并返回错误。
建议:D-Bus 调用失败时应该直接返回错误,而不是继续判断。

8. session/power1/power_save_plan.go - changeShortIdleState 阻塞 sleep

func (psp *powerSavePlan) changeShortIdleState(state bool) {
    // ...
    psp.setDsg(dsettingsShortIdleState, state)
    time.Sleep(300 * time.Millisecond)  // ← 阻塞 300ms
    callSetIdleState(state)
}

问题:在 metaTask 执行路径中阻塞 300ms,可能影响其他电源状态转换的响应时间。
建议:使用 time.AfterFunc 或在 goroutine 中处理,避免阻塞主流程。

9. session/power1/power_save_plan.go - getLaunchedApplications 性能问题

func getLaunchedApplications() []string {
    // 同步 D-Bus 调用,获取所有应用实例
}

问题:每次检查是否进入短 idle 时,都会同步查询 ApplicationManager 获取所有运行中的应用。在系统运行大量应用时,这可能导致明显的延迟。
建议:考虑缓存应用列表,或通过信号增量更新,而非每次全量查询。

10. session/power1/power_save_plan.go - isThirdPartyAppRunning 的启发式判断

if strings.Contains(desktop, "deepin") || strings.Contains(desktop, "dde") || strings.Contains(desktop, "uos") {
    logger.Warning("Need add systemApplicationsMap, Running app : ", app, desktop)
    continue
}

问题:仅通过文件名包含 deepin/dde/uos 来判断是否为系统应用过于宽泛,且日志级别为 Warning 但实际是正常业务逻辑。第三方应用也可能包含这些字符串。
建议:严格依赖 systemApplications 配置列表,如果发现缺失项应补充到配置中,而非运行时猜测。日志级别改为 Debug

11. system/power1/manager.go - setTlpModesetShortIdleState 中 goroutine 无错误反馈

go m.setDSPCState(_powerConfigMap[mode].DSPCConfig)
// ...
go func() {
    m.setDSPCState(_powerConfigMap[powerState].DSPCConfig)
    m.setDPCWifiState(wifiState)
}()

问题:异步执行但无任何错误处理或完成确认。如果设置失败,调用方完全无感知。
建议:至少添加错误日志;如果调用方需要知道结果,考虑使用 channel 或 callback。

12. 硬编码 LoongArch 路径缺乏架构保护

const (
    IdleFile       = "/sys/devices/system/loongarch/relax_state"
    IdleScreenFile = "/sys/devices/system/loongarch/idle_state"
)

问题:这些路径仅适用于 LoongArch 架构,在 x86/ARM 设备上文件不存在。
建议:添加架构检查(runtime.GOARCH),或在 getDsgValue 中通过 DSG 配置覆盖路径(当前已有此机制,但默认值仍会初始化为 LoongArch 路径)。

13. misc/dsg-configs/org.deepin.dde.daemon.power.json - shortIdleState 权限

"shortIdleState": {
    "permissions": "readwrite",
    "visibility": "private"
}

问题shortIdleState 被 session 侧和 system 侧同时写入,谁是权威来源?建议明确文档说明,或改为仅由一侧写入。


✅ 做得好的地方

  • DSG 配置结构清晰,配置项命名规范
  • systemApplications 白名单机制设计合理
  • 空闲延迟配置支持插电/电池分别设置
  • DPMS 屏幕状态同步到内核节点的逻辑清晰
  • exported_methods_auto.go 遵循项目约定

"dde-lock.desktop",
"dde-clipboard.desktop",
"dde-clipboard-daemon.desktop",
"dde-launcher.desktop",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1

"dde-file-manager.desktop",
"dde-computer.desktop",
"dde-trash.desktop",
"dde-control-center.desktop",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1

"deepin-diskmanager.desktop",
"deepin-camera.desktop",
"deepin-data-transfer.desktop",
"deepin-ab-recovery.desktop",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1

"gnome-keyring-ssh.desktop",
"gnome-keyring-pkcs11.desktop",
"gnome-keyring-secrets.desktop",
"fcitx-helper.desktop",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1

Comment thread misc/dsg-configs/org.deepin.dde.daemon.power.json
@deepin-bot
Copy link
Copy Markdown
Contributor

deepin-bot Bot commented May 20, 2026

TAG Bot

New tag: 6.1.90
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1117

@deepin-bot
Copy link
Copy Markdown
Contributor

deepin-bot Bot commented May 22, 2026

TAG Bot

New tag: 6.1.91
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1121

@deepin-bot
Copy link
Copy Markdown
Contributor

deepin-bot Bot commented May 25, 2026

TAG Bot

New tag: 6.1.92
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1127

@xionglinlin xionglinlin force-pushed the feat/short-idle-tlp branch from 77befed to 7d12dee Compare May 26, 2026 09:20
@deepin-bot
Copy link
Copy Markdown
Contributor

deepin-bot Bot commented May 28, 2026

TAG Bot

New tag: 6.1.93
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1131

1. Add short idle state management with kernel file writing via dde-
system-daemon
2. Add TLP mode setting interface in system power1
3. Implement short idle delay configuration and power saving plan
4. Add third-party application detection to control short idle entry
5. Add screen state from DPMS off/on events
6. Add DSG configuration for idle paths, delays, and blacklists

Log: Added short idle state management and TLP mode configuration for
power saving optimization

Influence:
1. Test short idle entry and exit with various delay configurations
2. Verify TLP mode switching via D-Bus interface
3. Test third-party application detection prevents short idle entry
4. Verify short idle blacklist and whitelist application behavior
5. Test screen state synchronization with DPMS events
6. Verify kernel file writing for idle and screen states
7. Test DSG configuration changes are properly applied

feat: 添加短idle和TLP模式支持

1. 通过dde-system-daemon添加短idle状态管理及内核文件写入功能
2. 在系统电源管理中新增TLP模式设置接口
3. 实现短idle延迟配置和节能计划管理
4. 添加第三方应用检测机制以控制短idle进入
5. 从DPMS关闭/打开事件同步屏幕状态
6. 新增DSG配置项:空闲路径、延迟时间和黑名单

Log: 新增短idle状态管理和TLP模式配置,优化节能策略

Influence:
1. 测试不同延迟配置下的短idle进入和退出
2. 通过D-Bus接口验证TLP模式切换功能
3. 测试第三方应用运行阻止短idle进入的逻辑
4. 验证短idle黑名单和白名单应用的行为
5. 测试屏幕状态与DPMS事件的同步
6. 验证空闲和屏幕状态的内核文件写入
7. 测试DSG配置变更的正确应用

PMS: TASK-389737
Change-Id: Ia3572bf438ff45f8c67e7f354f991fd6535f7775
@xionglinlin xionglinlin force-pushed the feat/short-idle-tlp branch from 7d12dee to 4d358ce Compare June 4, 2026 08:29
@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

这份代码提交主要实现了“短idle (Short Idle)”功能,涉及系统守护进程(dde-system-daemon)、会话电源管理(session/power1)和系统电源管理(system/power1)等多个模块的协同。整体逻辑是通过监听空闲时间,结合应用黑白名单判断是否进入短idle状态,进而控制EC(嵌入式控制器)状态、屏幕状态、WiFi节能模式以及CPU电源模式。

以下是针对语法逻辑、代码质量、性能和安全方面的详细审查意见和改进建议:

一、 语法与逻辑问题

  1. Map 初始化与清空逻辑错误

    • 文件: session/power1/power_save_plan.go
    • 位置: getSystemApplicationsgetShortIdleBlacklistApplications 函数
    • 问题: 代码写成了 if len(psp.manager.systemApplicationsMap) != 0 { psp.manager.systemApplicationsMap = make(map[string]string) }。这会导致当 Map 长度为 0 时,不会分配内存,后续的赋值操作会引发 panic。同时,这种清空方式也不直观。
    • 建议: 无论长度是否为0,都应该直接重新初始化:
      psp.manager.systemApplicationsMap = make(map[string]string)
      for _, app := range dsgSystemApplications {
          psp.manager.systemApplicationsMap[strings.ToLower(psp.getDesktopName(app))] = app
      }
  2. DBus 方法参数类型不匹配

    • 文件: keybinding1/utils.gosession/power1/power_save_plan.go
    • 位置: callSetScreenStatecallSetIdleState
    • 问题: dde-system-daemonexported_methods_auto.go 中定义的 InArgs 类型是 []string{"state"},这意味着 DBus 期望接收的参数类型可能是 boolint(取决于 dbusutil-gen 的解析,但通常布尔值对应 b)。然而在调用端,你使用了 dbus.MakeVariant(state),这会将参数包装为 Variant 类型 (v),导致 DBus 底层签名不匹配而调用失败。
    • 建议: 直接传递 state 变量,不要使用 dbus.MakeVariant
      err = systemConn.Object("org.deepin.dde.Daemon1", "/org/deepin/dde/Daemon1").Call("org.deepin.dde.Daemon1.SetScreenState", 0, state).Err
  3. setState 中的逻辑判断存在漏洞

    • 文件: bin/dde-system-daemon/power.go
    • 位置: setState 函数
    • 问题: 当 shortIdleState == state 时,代码直接 return errors.New("Short idle state not exchange."),这会导致即使当前需要写入内核文件,也会被跳过。如果因为某种原因 EC 状态与内核文件不同步,这里就会阻断状态同步。此外,如果 file != d.idleStatePath(比如是 idleScreenStatePath),获取 shortIdleState 来做拦截是不合逻辑的。
    • 建议: 去除这个强耦合的拦截逻辑,或者针对不同的文件做独立的状态记录和判断。如果只是为了防止重复写内核,应该读取内核文件当前值来判断,而不是依赖 DBus 属性。
  4. 第三方应用判断逻辑过于脆弱

    • 文件: session/power1/power_save_plan.go
    • 位置: isThirdPartyAppRunning
    • 问题: 判断系统应用的逻辑是:if strings.Contains(desktop, "deepin") || strings.Contains(desktop, "dde") || strings.Contains(desktop, "uos")。这种硬编码字符串匹配非常不严谨,第三方应用(如 deepin-wine 运行的应用、名为 dde-custom-tool 的脚本等)很容易绕过或被误判。
    • 建议: 严格依赖 systemApplicationsMap 白名单,移除这种基于名字的“猜测”逻辑。如果有遗漏的系统应用,应该通过更新 DConfig 配置文件来补充白名单,而不是在代码里打补丁。

二、 代码质量与可维护性

  1. 废弃的 ioutil

    • 文件: bin/dde-system-daemon/power.gosystem/power1/manager.go
    • 问题: ioutil.ReadFileioutil.WriteFile 在 Go 1.16 之后已被标记为废弃。
    • 建议: 替换为 os.ReadFileos.WriteFile
  2. 重复的 DBus 调用代码

    • 文件: keybinding1/utils.gosession/power1/power_save_plan.go
    • 问题: callSetScreenStatecallSetIdleState 在多个模块中重复定义,且实现几乎一模一样。
    • 建议: 将这些公共的 DBus 调用封装到同一个公共包(如 commonutils 包)中,避免代码冗余。
  3. time.Sleep 阻塞

    • 文件: session/power1/power_save_plan.go
    • 位置: changeShortIdleState
    • 问题: time.Sleep(300 * time.Millisecond) 会阻塞当前 goroutine。如果这是在主事件循环或重要的回调中,会导致不可预知的延迟。
    • 建议: 如果是为了等待 DBus 状态生效,应使用异步等待或状态机流转,而不是硬编码的 Sleep。至少应该放在单独的 goroutine 中或使用 time.AfterFunc
  4. 冗余的 syscall.Sync()

    • 文件: bin/dde-system-daemon/power.go
    • 位置: setState
    • 问题: 写入 sysfs 节点后调用 syscall.Sync() 会强制刷新整个文件系统的缓冲区,这是一个非常昂贵的操作,会导致 I/O 阻塞。sysfs 是虚拟文件系统,写入通常是对内核状态的直接映射,不需要文件系统级别的 sync。
    • 建议: 删除 syscall.Sync()

三、 代码性能

  1. 高频调用下的 DBus 通信开销

    • 文件: session/power1/power_save_plan.go
    • 位置: isThirdPartyAppRunning -> getLaunchedApplications
    • 问题: 每次判断是否进入短 idle 都会通过 DBus 调用 GetManagedObjects 获取所有运行中的应用。这个调用返回的数据量可能很大,且序列化/反序列化开销高。
    • 建议:
      • 缓存 launchedApplications 的结果。
      • 监听 ApplicationManager 的 InterfacesAdded / InterfacesRemoved 信号来增量更新缓存,而不是每次实时查询。
  2. 字符串操作优化

    • 文件: session/power1/power_save_plan.go
    • 位置: getDesktopName
    • 问题: 使用 strings.Split 切割路径获取文件名,会产生不必要的内存分配。
    • 建议: 使用 path.Basefilepath.Base,语义更清晰且性能更好:
      func (psp *powerSavePlan) getDesktopName(value string) string {
          return path.Base(value)
      }

四、 代码安全

  1. Sysfs 节点写入的权限与校验

    • 文件: bin/dde-system-daemon/power.go
    • 位置: setState
    • 问题: 代码通过 utils.IsFileExist(file) 判断文件存在后直接写入。虽然 file 的来源是 DConfig(默认为硬编码的 loongarch 节点),但 DConfig 是可以被修改的(即使权限是 readonly,也可能被 root 或同组用户修改配置文件)。
    • 建议:
      • 增加路径白名单校验,确保写入的路径必须在 /sys/devices/system/loongarch/ 目录下,防止通过篡改 DConfig 进行任意文件写入漏洞(虽然 daemon 是 root 运行,但防范配置篡改是必要的)。
      • ioutil.WriteFile(file, []byte(newContent), 0644) 权限设置对 sysfs 节点无实际意义,但建议权限收窄为 06000200
  2. DBus 接口暴露的安全风险

    • 文件: system/power1/manager_ifc.gobin/dde-system-daemon/exported_methods_auto.go
    • 问题: SetTlpModeSetShortIdleStateSetIdleStateSetScreenState 被导出为 DBus 方法,这意味着系统总线上的其他进程(包括用户态进程)可以随意调用这些接口,强制修改系统电源状态或写入内核节点。
    • 建议: 在 DBus 配置文件(XML policy)中严格限制这些方法的调用权限,仅允许 deepin-power 等特定服务或 root 用户调用,避免普通恶意应用干扰系统运行。
  3. 命令执行安全隐患

    • 文件: system/power1/manager_powersave.go
    • 位置: setDPCWifiState
    • 问题: 使用 systemd 临时单元执行 /usr/sbin/deepin-power-control idle wifi state。虽然 state 目前是硬编码的 on/off,但 setDPCWifiState 的参数来源于外部调用。
    • 建议: 在 setDPCWifiState 入口处严格校验 state 的值,确保只能是 shortIdleWifiOnshortIdleWifiOff,防止命令注入或不可预期的参数传递。

@deepin-bot
Copy link
Copy Markdown
Contributor

deepin-bot Bot commented Jun 4, 2026

TAG Bot

New tag: 6.1.94
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1138

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants