fix: Defer low-power mode during section indexing and book loading

Prevent the device from dropping to 10MHz CPU during first-time chapter
indexing, cover prerendering, and other CPU-intensive reader operations.

Three issues addressed:
- ActivityWithSubactivity now delegates preventAutoSleep() and
  skipLoopDelay() to the active subactivity, so EpubReaderActivity's
  signal is visible through the ReaderActivity wrapper
- Added post-loop() re-check of preventAutoSleep() in main.cpp to
  catch activity transitions that happen mid-loop
- EpubReaderActivity uses both !section and a loadingSection flag to
  cover the full duration from activity entry through section file
  creation; TxtReaderActivity uses !initialized similarly

Also syncs HalPowerManager.cpp log messages with upstream PR #852.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
cottongin
2026-02-15 16:42:27 -05:00
parent 3096d6066b
commit f90aebc891
6 changed files with 26 additions and 2 deletions

View File

@@ -17,14 +17,14 @@ void HalPowerManager::setPowerSaving(bool enabled) {
if (enabled && !isLowPower) {
LOG_DBG("PWR", "Going to low-power mode");
if (!setCpuFrequencyMhz(LOW_POWER_FREQ)) {
LOG_ERR("PWR", "Failed to set low-power CPU frequency");
LOG_DBG("PWR", "Failed to set CPU frequency = %d MHz", LOW_POWER_FREQ);
return;
}
}
if (!enabled && isLowPower) {
LOG_DBG("PWR", "Restoring normal CPU frequency");
if (!setCpuFrequencyMhz(normalFreq)) {
LOG_ERR("PWR", "Failed to restore normal CPU frequency");
LOG_DBG("PWR", "Failed to set CPU frequency = %d MHz", normalFreq);
return;
}
}

View File

@@ -14,4 +14,6 @@ class ActivityWithSubactivity : public Activity {
: Activity(std::move(name), renderer, mappedInput) {}
void loop() override;
void onExit() override;
bool preventAutoSleep() override { return subActivity && subActivity->preventAutoSleep(); }
bool skipLoopDelay() override { return subActivity && subActivity->skipLoopDelay(); }
};

View File

@@ -861,6 +861,8 @@ void EpubReaderActivity::renderScreen() {
}
if (!section) {
loadingSection = true;
const auto filepath = epub->getSpineItem(currentSpineIndex).href;
LOG_DBG("ERS", "Loading file: %s, index: %d", filepath.c_str(), currentSpineIndex);
section = std::unique_ptr<Section>(new Section(epub, currentSpineIndex, renderer));
@@ -880,6 +882,7 @@ void EpubReaderActivity::renderScreen() {
viewportHeight, SETTINGS.hyphenationEnabled, SETTINGS.embeddedStyle, popupFn)) {
LOG_ERR("ERS", "Failed to persist page data to SD");
section.reset();
loadingSection = false;
return;
}
} else {
@@ -912,6 +915,8 @@ void EpubReaderActivity::renderScreen() {
section->currentPage = newPage;
pendingPercentJump = false;
}
loadingSection = false;
}
renderer.clearScreen();

View File

@@ -29,6 +29,7 @@ class EpubReaderActivity final : public ActivityWithSubactivity {
bool pendingSubactivityExit = false; // Defer subactivity exit to avoid use-after-free
bool pendingGoHome = false; // Defer go home to avoid race condition with display task
bool skipNextButtonCheck = false; // Skip button processing for one frame after subactivity exit
volatile bool loadingSection = false; // True during the entire !section block (read from main loop)
const std::function<void()> onGoBack;
const std::function<void()> onGoHome;
@@ -55,4 +56,10 @@ class EpubReaderActivity final : public ActivityWithSubactivity {
void onEnter() override;
void onExit() override;
void loop() override;
// Defer low-power mode and auto-sleep while a section is loading/building.
// !section covers the period before the Section object is created (including
// cover prerendering in onEnter). loadingSection covers the full !section block
// in renderScreen (including createSectionFile), during which section is non-null
// but the section file is still being built.
bool preventAutoSleep() override { return !section || loadingSection; }
};

View File

@@ -57,4 +57,7 @@ class TxtReaderActivity final : public ActivityWithSubactivity {
void onEnter() override;
void onExit() override;
void loop() override;
// Defer low-power mode and auto-sleep while the reader is initializing
// (cover prerendering, page index building on first open).
bool preventAutoSleep() override { return !initialized; }
};

View File

@@ -440,6 +440,13 @@ void loop() {
}
}
// Re-check preventAutoSleep: the activity may have changed during loop() above
// (e.g., HomeActivity transitioned to EpubReaderActivity with pending section work).
if (currentActivity && currentActivity->preventAutoSleep()) {
lastActivityTime = millis();
powerManager.setPowerSaving(false);
}
// Add delay at the end of the loop to prevent tight spinning
// When an activity requests skip loop delay (e.g., webserver running), use yield() for faster response
// Otherwise, use longer delay to save power