Skip to content

feat(ambient-brightness): add ambient light sensor based auto brightn… - #118

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

feat(ambient-brightness): add ambient light sensor based auto brightn…#118
fly602 wants to merge 1 commit into
linuxdeepin:masterfrom
fly602:master

Conversation

@fly602

@fly602 fly602 commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

…ess plugin

Add a new ambient-brightness plugin that reads lux from iio-sensor-proxy, applies filtering, hysteresis, and debouncing, and publishes recommended brightness via DBus (org.deepin.dde.AmbientBrightness1). Refactor the power plugin to remove the old DConfig-based ambient brightness toggle, add isAmbientBrightnessActive() guard to PowerSavePlan so brightness save-plan operations don't conflict with ambient auto brightness. Remove redundant auto-brightness disable logic from dde-shortcut-tool since Display1.ChangeBrightness already calls prepareManualBrightnessChange() which disables ambient brightness via DBus.

新增环境光自动亮度插件,从 iio-sensor-proxy 读取 lux 值,经过滤波、滞回
和防抖处理后通过 DBus 发布推荐亮度。重构 power 插件,删除旧的 DConfig
自动亮度开关,在 PowerSavePlan 中添加 isAmbientBrightnessActive 守卫避免 省电计划与自动亮度冲突。移除 dde-shortcut-tool 中冗余的自动亮度关闭逻辑
(Display1.ChangeBrightness 已通过 prepareManualBrightnessChange 处理)。

Log: add ambient brightness plugin and refactor power/shortcut for auto brightness

Summary by Sourcery

Introduce a new ambient brightness plugin that exposes automatic brightness recommendations over DBus and integrates it with existing power and shortcut components.

New Features:

  • Add a session-level ambient-brightness plugin that reads lux from iio-sensor-proxy, applies filtering and hysteresis, and publishes recommended brightness via org.deepin.dde.AmbientBrightness1 on DBus.

Enhancements:

  • Integrate ambient brightness state with the power manager so power save brightness adjustments are skipped while auto brightness is active.
  • Remove legacy DConfig-based ambient auto brightness toggles and redundant manual disable logic from power and shortcut components, relying on the new ambient brightness service instead.
  • Add build and test infrastructure for the ambient-brightness plugin, including CMake setup, unit tests and Python-based tooling for sensor simulation and scenario testing.

Build:

  • Extend top-level and plugin CMake configuration to build and install the new ambient-brightness module and its tests.

Documentation:

  • Add README documentation for the ambient-brightness plugin and its continuous policy, configuration, lifecycle, and testing tools.

Tests:

  • Add unit tests for the continuous ambient light policy, brightness curve mapping, lifecycle state handling, model behavior, and ramp application tooling.
  • Add shell/Python-based scenario test scripts and tools to simulate ambient light changes and validate auto brightness ramp behavior.

@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, 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: 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 Jul 30, 2026

Copy link
Copy Markdown

Reviewer's Guide

Add a new ambient-brightness plugin that exposes org.deepin.dde.AmbientBrightness1 on D-Bus, implements continuous ambient light based brightness recommendation with hysteresis/debounce and lifecycle handling, wires it into the Qt plugin build, and refactors existing power and shortcut code to rely on the new DBus state instead of the old DConfig toggle, preventing conflicts with power save brightness adjustments.

Sequence diagram for ambient brightness recommendation and power-plan guard

sequenceDiagram
    participant SensorProxy as net_hadess_SensorProxy
    participant AmbientBrightnessService
    participant AmbientBrightnessModel
    participant ContinuousAmbientLightPolicy
    participant AmbientBrightness1 as org_deepin_dde_AmbientBrightness1
    participant SessionDBusProxy
    participant PowerManager
    participant PowerSavePlan

    SensorProxy->>AmbientBrightnessService: PropertiesChanged(LightLevel)
    AmbientBrightnessService->>AmbientBrightnessModel: submitSample(lux, timestamp)
    AmbientBrightnessModel->>ContinuousAmbientLightPolicy: update(SensorSample)
    ContinuousAmbientLightPolicy-->>AmbientBrightnessModel: Recommendation
    AmbientBrightnessModel-->>AmbientBrightnessService: recommendedBrightnessChanged(brightness)
    AmbientBrightnessService-->>AmbientBrightness1: PropertiesChanged(State=Active, RecommendedBrightness)

    PowerSavePlan->>PowerManager: isAmbientBrightnessActive()
    PowerManager->>SessionDBusProxy: isAmbientBrightnessActive()
    SessionDBusProxy->>AmbientBrightness1: get Property(State)
    AmbientBrightness1-->>SessionDBusProxy: State
    SessionDBusProxy-->>PowerManager: bool
    alt ambient brightness active
        PowerSavePlan-->>PowerSavePlan: [skip brightness change]
    else inactive
        PowerSavePlan-->>PowerSavePlan: applyBrightnessDrop()/resetBrightness()
    end
Loading

File-Level Changes

Change Details Files
Introduce a session-level ambient brightness service and continuous policy implementation driven by iio-sensor-proxy and DConfig.
  • Implement AmbientBrightnessService to manage sensor DBus interfaces, lifecycle (lid, sleep, login1 session), algorithm configuration, and org.deepin.dde.AmbientBrightness1 properties/signals.
  • Add AmbientBrightnessModel and an AmbientBrightnessPolicy abstraction, plus a ContinuousAmbientLightPolicy with ring buffer, weighted windows/raw modes, hysteresis, debounce and brightness recommendation logic.
  • Provide BrightnessCurve for log1p(lux)-space interpolation, a policy factory that reads DConfig JSON to build and configure the continuous policy, and tests for policy, curve, model and lifecycle.
  • Add debugging/testing scripts and Python/unittest harness for ambient-light-tool ramp behavior and scenario scripts.
src/plugin-qt/ambient-brightness/ambientbrightnessservice.cpp
src/plugin-qt/ambient-brightness/ambientbrightnessservice.h
src/plugin-qt/ambient-brightness/ambientbrightnessmodel.cpp
src/plugin-qt/ambient-brightness/ambientbrightnessmodel.h
src/plugin-qt/ambient-brightness/ambientbrightnesspolicy.h
src/plugin-qt/ambient-brightness/ambientbrightnesspolicyfactory.cpp
src/plugin-qt/ambient-brightness/ambientbrightnesspolicyfactory.h
src/plugin-qt/ambient-brightness/continuous/continuousambientlightpolicy.cpp
src/plugin-qt/ambient-brightness/continuous/continuousambientlightpolicy.h
src/plugin-qt/ambient-brightness/brightnesscurve.cpp
src/plugin-qt/ambient-brightness/brightnesscurve.h
src/plugin-qt/ambient-brightness/ambientlightlifecyclestate.h
src/plugin-qt/ambient-brightness/ambientbrightnesslogging.cpp
src/plugin-qt/ambient-brightness/ambientbrightnesslogging.h
src/plugin-qt/ambient-brightness/plugin.cpp
src/plugin-qt/ambient-brightness/CMakeLists.txt
src/plugin-qt/ambient-brightness/tests/*
src/plugin-qt/ambient-brightness/scripts/*
src/plugin-qt/ambient-brightness/configs/org.deepin.dde.daemon.ambient-brightness.json
src/plugin-qt/ambient-brightness/misc/ambient-brightness.service
src/plugin-qt/ambient-brightness/misc/plugin-ambient-brightness.json
Integrate the ambient-brightness plugin into the Qt plugin build and enable CTest-based testing.
  • Include CTest at top-level and in the ambient-brightness CMake to enable BUILD_TESTING.
  • Add ambient-brightness subdirectory to src/plugin-qt/CMakeLists.txt and define a MODULE library linked against Qt Core/DBus and Dtk Core/DConfig.
  • Install the plugin module, service-manager JSON, DBus service file, and DConfig metadata into appropriate install dirs.
  • Add CMake test targets for continuous policy, brightness curve, model, lifecycle, and Python-based ambient-light-tool ramp tests.
CMakeLists.txt
src/plugin-qt/CMakeLists.txt
src/plugin-qt/ambient-brightness/CMakeLists.txt
src/plugin-qt/ambient-brightness/tests/CMakeLists.txt
Expose ambient brightness active state to the power session via DBus and guard power save brightness operations when auto brightness is active.
  • Extend SessionDBusProxy to create an org.deepin.dde.AmbientBrightness1 DDBusInterface and add isAmbientBrightnessActive() reading its State property.
  • Add PowerManager::isAmbientBrightnessActive() delegating to the proxy, and use it in PowerSavePlan::resetBrightness/applyBrightnessDrop to skip brightness changes and clear m_oldBrightness when ambient auto brightness is active.
  • Initialize login1 session and power lifecycle hooks inside AmbientBrightnessService to coordinate enabling/disabling sensor claims with power events.
src/plugin-qt/power/session/sessiondbusproxy.cpp
src/plugin-qt/power/session/sessiondbusproxy.h
src/plugin-qt/power/session/powermanager.cpp
src/plugin-qt/power/session/powermanager.h
src/plugin-qt/power/session/powersaveplan.cpp
Remove legacy DConfig-based ambient brightness toggle and redundant shortcut-side disabling logic now that Display1/ambient-brightness service coordinate auto brightness state.
  • Delete AmbientLightAdjustBrightness Q_PROPERTY, setter/getter, backing field and DConfig init wiring from PowerManager and PowerDConfig.
  • Remove the KEY_AMBIENT_LIGHT_ADJUST_BRIGHTNESS constant from dde-shortcut-tool constants.
  • Simplify DisplayController::changeBrightness by removing DConfig access and ambientLightAdjustBrightness disabling, relying on Display1.ChangeBrightness/prepareManualBrightnessChange to handle DBus-based ambient brightness disable.
  • Drop DConfig include and namespace use from dde-shortcut-tool displaycontroller.cpp.
src/plugin-qt/power/session/powermanager.cpp
src/plugin-qt/power/session/powermanager.h
src/plugin-qt/power/powerconstants.h
src/plugin-qt/shortcut/tools/dde-shortcut-tool/constant.h
src/plugin-qt/shortcut/tools/dde-shortcut-tool/displaycontroller.cpp

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

@fly602
fly602 force-pushed the master branch 4 times, most recently from 8ae717f to e346e81 Compare July 31, 2026 06:59
@deepin-bot

deepin-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 1.0.37
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #124

1. Add an ambient brightness service backed by iio-sensor-proxy
2. Convert lux samples into stable brightness recommendations with filtering, hysteresis, and debounce
3. Coordinate sensor lifecycle with lid, sleep, session, service, and configuration state

Influence:
1. Publish automatic brightness state and recommendations through org.deepin.dde.AmbientBrightness1
2. Prevent power-saving and manual brightness paths from conflicting with ambient brightness
3. Verify sensor lifecycle and brightness policy with unit tests

fix: 支持环境光自动亮度调节

1. 新增基于iio-sensor-proxy的环境光亮度服务
2. 通过滤波、滞回和防抖将lux样本转换为稳定的亮度推荐值
3. 根据合盖、休眠、会话、传感器服务及配置状态管理光感生命周期

Influence:
1. 通过org.deepin.dde.AmbientBrightness1发布自动亮度状态及推荐值
2. 避免省电及手动亮度调节路径与环境光自动亮度冲突
3. 通过单元测试验证光感生命周期及亮度策略

PMS: BUG-372191
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:88分

■ 【总体评价】

代码实现了环境光传感器数据采集与亮度推荐功能,架构清晰、分层合理,但存在代码重复及违反 Qt 对象树规范的轻微问题
逻辑正确但因重复代码和不当的对象生命周期管理扣12分

■ 【详细分析】

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

代码整体逻辑严谨,状态机转换清晰。connectSensor 函数中针对 ClaimLight 同步调用期间可能收到信号的情况,设计了 m_claimInProgress 机制进行防御性捕获,无论底层 Qt D-Bus 实现在同步调用时是否分发排队信号,该逻辑均能保证初始样本不丢失或安全回退到超时兜底读取,无逻辑漏洞。
建议:可添加简短注释说明该防御机制在不同 Qt 版本下的行为差异,以提升可维护性。

  • 2.代码质量(一般)✕

onAutomaticBrightnessEnabledChangedEnable 两个方法中存在完全相同的 5 行传感器释放与状态重置代码,违反 DRY 原则。此外,在 connectSensordisconnectSensor 中,m_sensor 在创建时传入了 this 作为 parent(new QDBusInterface(..., this)),但随后又使用了 delete m_sensor; 进行手动释放。在 Qt 中手动 delete 具有 parent 的对象是不规范的做法,尽管此处因紧接着置空了指针而不会引发双重释放崩溃,但破坏了 Qt 对象树的内存管理语义,增加维护风险。
潜在问题:代码重复增加维护成本;手动释放带 parent 的 QObject 违反 Qt 编程规范。
建议:提取重复的停止逻辑为独立的 stopSensorAndReset() 私有方法;创建 QDBusInterface 时将 parent 参数传为 nullptr,使手动 delete 合法化。

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

算法层使用了按需扩容的环形缓冲区存储 lux 样本,时间复杂度和空间复杂度控制良好。服务层使用单次触发的 QTimer 进行 debounce 确认,避免了无意义的轮询开销。D-Bus 通信仅在状态变更和样本到达时触发,无性能瓶颈。
建议:当前性能表现优异,无需额外优化。

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

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
代码对外部输入(D-Bus 传感器属性、DConfig 配置项)均进行了严格的类型校验和边界检查。variantToValidLux 拒绝非有限值和负数;parseCurvePointsBrightnessCurve::isValid 对 JSON 曲线控制点进行了严格的单调性、范围和结构校验,非法配置会安全回退到内置默认值,不存在命令注入、缓冲区溢出或越界访问等安全漏洞。
建议:继续保持对外部输入的严格校验策略。

■ 【改进建议代码示例】

// ambientbrightnessservice.h 中新增私有方法声明
private:
    void stopSensorAndReset();
    void connectSensor();
    void disconnectSensor();
    // ...

// ambientbrightnessservice.cpp 中的实现修改
void AmbientBrightnessService::stopSensorAndReset()
{
    stopInitialSampleWait();
    if (m_evaluationTimer)
        m_evaluationTimer->stop();
    if (m_sensor && m_claimed)
        m_sensor->call(QStringLiteral("ReleaseLight"));
    m_claimed = false;
    m_haveSample = false;
    m_model.setDisabled();
}

void AmbientBrightnessService::onAutomaticBrightnessEnabledChanged(bool enabled)
{
    if (m_lifecycle.enabled == enabled)
        return;
    qCDebug(logAmbientBrightness) << "configured enabled=" << enabled;
    m_lifecycle.enabled = enabled;
    Q_EMIT enabledChanged(enabled);
    publishPropertyChange(QStringLiteral("Enabled"), enabled);
    if (!enabled) {
        stopSensorAndReset();
    } else {
        refreshSensorConnection();
    }
}

void AmbientBrightnessService::Enable(bool active)
{
    qCDebug(logAmbientBrightness) << "enable requested=" << active;
    m_lifecycle.enabled = active;
    Q_EMIT enabledChanged(active);
    publishPropertyChange(QStringLiteral("Enabled"), active);
    if (m_config && m_config->isValid())
        m_config->setValue(QString::fromLatin1(kAmbientLightAdjustBrightnessKey), active);

    if (!active) {
        stopSensorAndReset();
    } else {
        refreshSensorConnection();
    }
}

void AmbientBrightnessService::connectSensor()
{
    disconnectSensor();
    auto systemBus = QDBusConnection::systemBus();
    // 修复:传入 nullptr 作为 parent,交由 disconnectSensor 手动管理生命周期
    m_sensor = new QDBusInterface(QString::fromLatin1(kSensorService),
                                  QString::fromLatin1(kSensorPath),
                                  QString::fromLatin1(kSensorInterface),
                                  systemBus, nullptr);
    if (!m_sensor->isValid()) {
        qCWarning(logAmbientBrightness) << "sensor interface invalid";
        delete m_sensor;
        m_sensor = nullptr;
        m_model.makeUnavailable();
        return;
    }
    // ... 后续逻辑保持不变 ...
}

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