Skip to content

refactor(display): refactor auto brightness logic - #1192

Open
fly602 wants to merge 1 commit into
linuxdeepin:masterfrom
fly602:master
Open

refactor(display): refactor auto brightness logic#1192
fly602 wants to merge 1 commit into
linuxdeepin:masterfrom
fly602:master

Conversation

@fly602

@fly602 fly602 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor
  1. Use AmbientBrightness1 as the recommendation source and let Display1 arbitrate automatic and manual brightness updates.
  2. Refactor brightness transitions to support target updates and deterministic cancellation.
  3. Move power-saving brightness scaling to Display1 while keeping persisted brightness values unscaled.
  4. Remove the obsolete sensor, filtering, curve, and power-saving dimming logic from Display1 and session/power1.
  5. Remove dde-daemon's iio-sensor-proxy recommendation because sensor access is now owned by AmbientBrightness1.
  6. Add regression tests and documentation for the new brightness architecture.

Log: Refactor auto brightness logic and centralize brightness arbitration in Display1.

Influence:

  1. Verify automatic brightness follows recommendations from AmbientBrightness1.
  2. Verify manual brightness changes stop automatic transitions and disable automatic adjustment.
  3. Verify power-saving scaling affects hardware brightness without changing persisted values.
  4. Verify brightness transitions can update targets and stop cleanly.

refactor(display): 重构自动亮度逻辑

  1. 使用 AmbientBrightness1 提供推荐亮度,由 Display1 统一仲裁自动和手动亮度更新。
  2. 重构亮度渐变逻辑,支持动态更新目标值和确定性停止渐变任务。
  3. 将节能亮度缩放迁移到 Display1,同时保持持久化亮度值不受缩放影响。
  4. 移除 Display1 和 session/power1 中陈旧的传感器、滤波、曲线及节能调光逻辑。
  5. 光感访问已由 AmbientBrightness1 负责,因此移除 dde-daemon 对 iio-sensor-proxy 的推荐依赖。
  6. 为新的亮度架构补充回归测试和设计文档。

Log: 重构自动亮度逻辑,由 Display1 统一仲裁亮度更新。

Influence:

  1. 验证自动亮度能够正确应用 AmbientBrightness1 的推荐值。
  2. 验证手动调节亮度时会停止自动渐变并关闭自动调节。
  3. 验证节能缩放影响实际亮度,但不会修改持久化亮度值。
  4. 验证亮度渐变能够动态更新目标并可靠停止。

PMS: BUG-372191

Summary by Sourcery

Centralize auto-brightness arbitration in Display1 using AmbientBrightness1 recommendations, introduce a new deterministic brightness transition engine, and apply power-saving brightness scaling in Display1 without persisting scaled values.

Enhancements:

  • Replace legacy sensor and auto-brightness implementation in Display1 with an AmbientBrightness1-backed recommendation client and a simplified manager.
  • Introduce a single-worker brightness transition component that supports dynamic target updates and synchronous cancellation for auto-brightness.
  • Move power-saving brightness scaling from session/power1 into Display1, keeping stored brightness values unscaled while scaling hardware writes.
  • Remove obsolete ambient light, brightness curve, Kalman filter, and power-saving dimming logic from Display1 and session/power1, simplifying configuration and code paths.

Documentation:

  • Add architecture documentation describing the responsibilities of AmbientBrightness1, Display1, and Power1, and how auto-brightness and power-saving scaling interact.

Tests:

  • Add unit tests covering recommendation state parsing, ambient brightness lifecycle behaviour, and the new brightness transition semantics in Display1.

1. Use AmbientBrightness1 as the recommendation source and let Display1 arbitrate automatic and manual brightness updates.
2. Refactor brightness transitions to support target updates and deterministic cancellation.
3. Move power-saving brightness scaling to Display1 while keeping persisted brightness values unscaled.
4. Remove the obsolete sensor, filtering, curve, and power-saving dimming logic from Display1 and session/power1.
5. Remove dde-daemon's iio-sensor-proxy recommendation because sensor access is now owned by AmbientBrightness1.
6. Add regression tests and documentation for the new brightness architecture.

Log: Refactor auto brightness logic and centralize brightness arbitration in Display1.

Influence:
1. Verify automatic brightness follows recommendations from AmbientBrightness1.
2. Verify manual brightness changes stop automatic transitions and disable automatic adjustment.
3. Verify power-saving scaling affects hardware brightness without changing persisted values.
4. Verify brightness transitions can update targets and stop cleanly.

refactor(display): 重构自动亮度逻辑

1. 使用 AmbientBrightness1 提供推荐亮度,由 Display1 统一仲裁自动和手动亮度更新。
2. 重构亮度渐变逻辑,支持动态更新目标值和确定性停止渐变任务。
3. 将节能亮度缩放迁移到 Display1,同时保持持久化亮度值不受缩放影响。
4. 移除 Display1 和 session/power1 中陈旧的传感器、滤波、曲线及节能调光逻辑。
5. 光感访问已由 AmbientBrightness1 负责,因此移除 dde-daemon 对 iio-sensor-proxy 的推荐依赖。
6. 为新的亮度架构补充回归测试和设计文档。

Log: 重构自动亮度逻辑,由 Display1 统一仲裁亮度更新。

Influence:
1. 验证自动亮度能够正确应用 AmbientBrightness1 的推荐值。
2. 验证手动调节亮度时会停止自动渐变并关闭自动调节。
3. 验证节能缩放影响实际亮度,但不会修改持久化亮度值。
4. 验证亮度渐变能够动态更新目标并可靠停止。

PMS: BUG-372191

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry @fly602, your pull request is larger than the review limit of 150000 diff characters

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: fly602

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

@sourcery-ai

sourcery-ai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refactors auto-brightness to consume recommendations from AmbientBrightness1, replaces the generic TransitionManager with a dedicated brightness transition state machine, and centralizes power-saving brightness scaling inside Display1 while removing legacy sensor and power-saving brightness logic from session/power1 and keybinding1.

Sequence diagram for applying ambient recommendation and handling manual brightness

sequenceDiagram
  actor User
  participant Manager as Display1_Manager
  participant Auto as AutoBrightnessManager
  participant Client as RecommendationClient
  participant Trans as BrightnessTransition

  Client->>Client: Refresh()
  Client-->>Auto: onAmbientBrightnessStateChanged(state)
  Auto->>Manager: setPropAutoBrightnessEnabled(state.Enabled)
  Auto->>Trans: applyRecommendedBrightness()
  Trans->>Manager: setBrightnessAndSync(monitorName, scaledValue)

  User->>Manager: SetAndSaveBrightness(outputName, value)
  Manager->>Auto: prepareManualBrightnessChange()
  Auto->>Trans: DisableForManualAdjustment()
  Trans->>Trans: Stop()
  Auto->>Client: Enable(false)
  Client-->>Auto: onAmbientBrightnessStateChanged(disabledState)
  Manager->>Manager: setBrightnessAndSync(outputName, value)
  Manager->>Manager: saveBrightnessInCfg(map[outputName]value)
Loading

File-Level Changes

Change Details Files
AutoBrightnessManager now consumes AmbientBrightness1 recommendations and arbitrates automatic vs manual brightness within Display1.
  • Removed SensorProxy-based ambient light acquisition, Kalman filtering, custom curves, and dconf-backed auto-brightness configuration from Display1.
  • Introduced RecommendationClient to track AmbientBrightness1 state and recommended brightness via PropertiesChanged and NameOwnerChanged signals.
  • AutoBrightnessManager was rewritten to manage enable/disable through AmbientBrightness1.Enable, apply recommendations via a local BrightnessTransition, and expose IsSupported/IsEnabled/IsRunning/GetStatus in terms of AmbientBrightness1 state.
  • Manual brightness operations now call DisableForManualAdjustment on AutoBrightnessManager so manual changes synchronously cancel and disable automatic brightness.
display1/auto_brightness.go
display1/recommendation_client.go
display1/auto_brightness_test.go
display1/manager.go
display1/manager_ifc.go
Brightness transitions were redesigned as a single-worker state machine that supports target updates, deterministic cancellation, and on-complete callbacks.
  • Replaced TransitionManager/TransitionExecutor (per-monitor, type-aware, configurable, dconf-driven) with a lightweight BrightnessTransition that runs a single goroutine per auto transaction.
  • BrightnessTransition now exposes Run(from,to), Update(target), Stop(), IsRunning(), and SetOnComplete, with a fixed ramp duration, easing function, and hardware step threshold.
  • Display1 uses BrightnessTransition inside AutoBrightnessManager to smooth automatic brightness changes and to save the unscaled recommended brightness to configuration on normal completion.
  • Removed curve-based and transition configuration keys from Display1 dconfig handling and related helper code in brightness/curve.go and brightness_transition.go.
display1/brightness/brightness_transition.go
display1/auto_brightness.go
display1/brightness.go
display1/manager.go
display1/brightness/brightness.go
Power-saving brightness scaling is now handled in Display1 using a non-persisted scale factor derived from Power1 properties.
  • Added brightnessScale field and mutexes to Manager, along with initBrightnessScale, calcBrightnessScale, onPowerSavingModeChanged, applyBrightnessScale, get/setBrightnessScale, and scaleBrightness helpers.
  • Display1 listens to PowerSavingModeEnabled and PowerSavingModeBrightnessDropPercent from system Power1, computes a scale, and applies it when initializing brightness, refreshing brightness, applying monitor configs, and using automatic brightness recommendations.
  • Persisted SysMonitorConfig.Brightness remains unscaled logical brightness; scaleBrightness is only applied when writing to hardware or deriving current brightness for color temperature.
  • New brightness writes serialize via brightnessWriteMu to avoid races between scale application and manual/auto transactions.
display1/brightness_scale.go
display1/brightness.go
display1/manager.go
display1/color_temp.go
display1/monitor.go
Removed legacy ambient light sensor integration and power-saving brightness management from session/power1 and keybinding1.
  • Deleted ambient light sensor fields, configuration keys, D-Bus properties, claim/release logic, and light-level handlers from session/power1 Manager and helper.
  • Removed multiBrightnessWithPsm, PowerSavingModeBrightnessData synchronization, and in-session brightness scaling logic; power-saving mode callbacks now only persist the enabled flag.
  • Keybinding1 no longer directly toggles ambient-light-adjust-brightness in power settings when handling brightness hotkeys.
  • Removed SensorProxy client usage and associated signal wiring from session/power1 helper and lid-switch handling.
session/power1/manager.go
session/power1/power_save_plan.go
session/power1/power_dbusutil.go
session/power1/helper.go
session/power1/constant.go
session/power1/lid_switch.go
keybinding1/display_controller.go
keybinding1/constants/dsettings.go
Adjusted Display1 initialization and config application paths to correctly interact with AmbientBrightness1 and brightness scaling.
  • On startup and when applying system monitor configs, Display1 queries AmbientBrightness1 state synchronously; when ambient is enabled, supported, active, and has a valid recommendation, it prefers the recommended brightness over saved config for the builtin monitor.
  • When ambient is enabled but not active or unsupported, Display1 logs and falls back to saved brightness for the builtin monitor.
  • Brightness-related methods such as initBrightness, RefreshBrightness, applySysMonitorConfigs, and color temperature one-shot now consistently use scaleBrightness with the current brightnessScale.
  • Auto-brightness initialization no longer pulls local config; instead it mirrors AmbientBrightness1’s Enabled/Supported into Display1 properties and relies on RecommendationClient state callbacks.
display1/manager.go
display1/brightness.go
display1/color_temp.go
display1/manager_lid.go
Added documentation and tests to cover the new brightness architecture and recommendation lifecycle.
  • Introduced docs/brightness-architecture.md describing responsibilities of AmbientBrightness1, Display1, and Power1, auto-brightness lifecycle, power-saving brightness scaling, and persistence semantics.
  • Added tests for RecommendationClient state parsing and PropertiesChanged handling, including invalid RecommendedBrightness recovery and lifecycle transitions.
  • Added tests for BrightnessTransition behavior: Update reaching the latest target, Stop waiting for in-flight writes, Stop-before-Run, and application lifecycle gating for recommendations.
  • Removed obsolete auto-brightness dsg configs and ambient light tests from session/power1, aligning tests with the new architecture.
docs/brightness-architecture.md
display1/auto_brightness_test.go
display1/recommendation_client.go
display1/brightness/brightness_transition.go
misc/dsg-configs/org.deepin.Display.AutoBrightness.json
session/power1/ambient_light_test.go

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:95分

■ 【总体评价】

代码成功实现了自动亮度架构从直接消费传感器到消费推荐服务的解耦重构,消除了历史技术债务
逻辑严密、性能优化显著且无安全漏洞,因极少量防御性代码可进一步精简扣5分

■ 【详细分析】

  • 1.语法逻辑(完全正确)✓

重构后的状态机逻辑清晰,AutoBrightnessManager 通过 running 标志位精确控制渐变生命周期。在 BrightnessTransition.loop 中,通过 revision 机制完美解决了渐变期间 Update 重定向目标导致的起算点错乱问题。锁的层级设计合理,applyMu 保证了 applyRecommendedBrightness 的串行执行,mutex 保护了状态一致性,brightnessWriteMu 保证了硬件写入的原子性,未发现死锁或竞态条件风险。
建议:在 BrightnessTransition.loop 中对 setter == nil 的检查可移至 Run 函数入口处,避免在每次 tick 中进行冗余判断。

  • 2.代码质量(优秀)✓

架构解耦彻底,将光感采样、卡尔曼滤波、亮度计算等职责完全上移至 AmbientBrightness1,Display1 仅保留消费推荐值与节能缩放职责,消除了旧代码中 multiBrightnessWithPsm 等复杂状态同步逻辑。新增的 docs/brightness-architecture.md 文档详尽描述了各模块契约与亮度写入路径。配套的 auto_brightness_test.go 覆盖了状态解析、渐变重定向、停止同步等核心边界场景,测试用例设计严谨。
建议:RecommendationClient.handlePropertiesChanged 函数较长,可将 changed 字典的解析逻辑提取为独立的 applyChangedProperties 方法以提升可读性。

  • 3.代码性能(高效)✓

彻底移除了旧架构中 150ms 间隔的 compensationTicker 轮询机制,改为纯事件驱动的 PropertiesChanged 监听,大幅降低了无光照变化时的 CPU 唤醒与 D-Bus 开销。新的渐变算法采用 50ms tick 配合 smoothstep 缓动与 hwBrightnessStep 阈值跳过机制,在保证视觉平滑的同时,将渐变总时长从 4000ms 缩短至 800ms,响应更敏捷且系统调用次数更少。
建议:无。

  • 4.代码安全(存在0个安全漏洞)✓

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
代码对外部 D-Bus 输入进行了严格的校验与隔离。在 parseRecommendationStatehandlePropertiesChanged 中,对所有属性进行了严格的类型断言检查,失败时降级为安全默认值而非 panic。RecommendedBrightness 经过了 isValidRecommendedBrightness 校验,拦截了 NaNInf 及越界值。scaleBrightnesscalcBrightnessScale 对计算结果进行了严格的边界钳位,防止异常浮点数写入背光硬件。
建议:无。

■ 【改进建议代码示例】

// display1/recommendation_client.go
// 将属性解析逻辑提取为独立方法,提升 handlePropertiesChanged 的可读性与可维护性

// applyChangedProperties 将 D-Bus 变更字典应用到状态副本上。
// 对所有外部输入进行严格类型检查,失败时记录警告并使用安全默认值。
func applyChangedProperties(state RecommendationState, changed map[string]dbus.Variant) RecommendationState {
	if value, ok := changed["Enabled"]; ok {
		enabled, validType := value.Value().(bool)
		if !validType {
			logger.Warningf("[AutoBrightness] Invalid Enabled property type %T", value.Value())
			state.Enabled = false
		} else {
			state.Enabled = enabled
		}
	}

	if value, ok := changed["State"]; ok {
		stateName, validType := value.Value().(string)
		if !validType {
			logger.Warningf("[AutoBrightness] Invalid State property type %T", value.Value())
			state.State = ""
		} else {
			state.State = stateName
		}
	}

	if value, ok := changed["Supported"]; ok {
		supported, validType := value.Value().(bool)
		if !validType {
			logger.Warningf("[AutoBrightness] Invalid Supported property type %T", value.Value())
			state.Supported = false
		} else {
			state.Supported = supported
		}
	}

	if value, ok := changed["RecommendedBrightness"]; ok {
		recommended, validType := value.Value().(float64)
		if !validType || !isValidRecommendedBrightness(recommended) {
			logger.Warningf("[AutoBrightness] Invalid RecommendedBrightness value %v", value.Value())
			state.RecommendedBrightness = math.NaN()
		} else {
			state.RecommendedBrightness = recommended
		}
	}

	return state
}

// handlePropertiesChanged 处理推荐服务属性变化信号(重构后版本)
func (c *RecommendationClient) handlePropertiesChanged(interfaceName string,
	changed map[string]dbus.Variant, invalidated []string) {
	if interfaceName != ambientBrightnessInterface {
		return
	}

	c.mu.Lock()
	state := c.state
	state.Available = true

	for _, name := range invalidated {
		switch name {
		case "Enabled":
			state.Enabled = false
		case "State":
			state.State = ""
		case "Supported":
			state.Supported = false
		case "RecommendedBrightness":
			state.RecommendedBrightness = math.NaN()
		}
	}

	// 使用提取出的独立方法处理变更字典
	state = applyChangedProperties(state, changed)

	if state == c.state {
		c.mu.Unlock()
		return
	}
	c.state = state
	callback := c.callback
	c.mu.Unlock()

	if callback != nil {
		callback(state)
	}
}

@fly602
fly602 requested a review from deepin-ci-robot August 4, 2026 03:37
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.

2 participants