diff --git a/src/app/application_services.cpp b/src/app/application_services.cpp index 9eee4f003b..87dec85cff 100644 --- a/src/app/application_services.cpp +++ b/src/app/application_services.cpp @@ -999,6 +999,8 @@ void Application::initSystemBusServices() { // fade-complete cleanup races with process freeze. m_idleGraceOverlay.hide(); if (sleeping) { + // Screen time must not accumulate across suspend even when lock-before-suspend is off. + m_screenTimeService.setSuspendPaused(true); // Delay inhibit (when lock_before_suspend is on) holds sleep until we lock. // Do not use runAfterSessionLocked here — that slot belongs to lock-and-suspend. if (m_skipLockOnNextSleep) { @@ -1046,6 +1048,7 @@ void Application::initSystemBusServices() { } m_skipLockOnNextSleep = false; m_releaseSleepDelayWhenLocked = false; + m_screenTimeService.setSuspendPaused(false); if (m_configService.shouldLockBeforeSuspend() && m_logindService != nullptr) { (void)m_logindService->acquireSleepDelayInhibit(); } diff --git a/src/system/screen_time_service.cpp b/src/system/screen_time_service.cpp index b9cd001232..e9cef88fa8 100644 --- a/src/system/screen_time_service.cpp +++ b/src/system/screen_time_service.cpp @@ -313,10 +313,7 @@ void ScreenTimeService::setEnabled(bool enabled) { } m_tickTimer.stop(); } else { - if (!m_sessionLocked) { - onFocusChange(); - m_tickTimer.startRepeating(kTickInterval, [this]() { tick(); }); - } + resumeTracking(); } if (m_changeCallback) { m_changeCallback(); @@ -327,29 +324,48 @@ void ScreenTimeService::setSessionLocked(bool locked) { if (m_sessionLocked == locked) { return; } - m_sessionLocked = locked; if (locked) { - if (m_enabled) { - flushActiveSession(std::chrono::steady_clock::now()); - if (m_dirty) { - save(); - } - } - m_activeAppKey.clear(); - m_activeSince = {}; - m_tickTimer.stop(); + pauseTracking(); + return; + } + resumeTracking(); +} + +void ScreenTimeService::setSuspendPaused(bool paused) { + if (m_suspendPaused == paused) { + return; + } + m_suspendPaused = paused; + if (paused) { + pauseTracking(); return; } + resumeTracking(); +} +void ScreenTimeService::pauseTracking() { if (m_enabled) { - onFocusChange(); - m_tickTimer.startRepeating(kTickInterval, [this]() { tick(); }); + flushActiveSession(std::chrono::steady_clock::now()); + if (m_dirty) { + save(); + } + } + m_activeAppKey.clear(); + m_activeSince = {}; + m_tickTimer.stop(); +} + +void ScreenTimeService::resumeTracking() { + if (!m_enabled || m_sessionLocked || m_suspendPaused) { + return; } + onFocusChange(); + m_tickTimer.startRepeating(kTickInterval, [this]() { tick(); }); } void ScreenTimeService::onFocusChange() { - if (!m_enabled || m_sessionLocked) { + if (!m_enabled || m_sessionLocked || m_suspendPaused) { return; } const std::string candidate = appKeyForActive(); @@ -372,7 +388,7 @@ void ScreenTimeService::onFocusChange() { } void ScreenTimeService::tick() { - if (!m_enabled || m_sessionLocked) { + if (!m_enabled || m_sessionLocked || m_suspendPaused) { return; } const bool wasDirty = m_dirty; diff --git a/src/system/screen_time_service.h b/src/system/screen_time_service.h index dcf0fdc178..c38c3726a7 100644 --- a/src/system/screen_time_service.h +++ b/src/system/screen_time_service.h @@ -49,6 +49,7 @@ class ScreenTimeService { void setChangeCallback(std::function callback); void setEnabled(bool enabled); void setSessionLocked(bool locked); + void setSuspendPaused(bool paused); [[nodiscard]] bool enabled() const noexcept { return m_enabled; } [[nodiscard]] ScreenTimeSnapshot snapshot(int rangeDays = 1); @@ -64,7 +65,8 @@ class ScreenTimeService { std::unordered_map> appHourly; std::array hourly{}; }; - + void pauseTracking(); + void resumeTracking(); void tick(); void flushActiveSession(std::chrono::steady_clock::time_point now); void ensureCurrentDayLocked(std::chrono::system_clock::time_point now); @@ -98,4 +100,5 @@ class ScreenTimeService { bool m_dirty = false; bool m_enabled = false; bool m_sessionLocked = false; + bool m_suspendPaused = false; };