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:
@@ -17,14 +17,14 @@ void HalPowerManager::setPowerSaving(bool enabled) {
|
|||||||
if (enabled && !isLowPower) {
|
if (enabled && !isLowPower) {
|
||||||
LOG_DBG("PWR", "Going to low-power mode");
|
LOG_DBG("PWR", "Going to low-power mode");
|
||||||
if (!setCpuFrequencyMhz(LOW_POWER_FREQ)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!enabled && isLowPower) {
|
if (!enabled && isLowPower) {
|
||||||
LOG_DBG("PWR", "Restoring normal CPU frequency");
|
LOG_DBG("PWR", "Restoring normal CPU frequency");
|
||||||
if (!setCpuFrequencyMhz(normalFreq)) {
|
if (!setCpuFrequencyMhz(normalFreq)) {
|
||||||
LOG_ERR("PWR", "Failed to restore normal CPU frequency");
|
LOG_DBG("PWR", "Failed to set CPU frequency = %d MHz", normalFreq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,4 +14,6 @@ class ActivityWithSubactivity : public Activity {
|
|||||||
: Activity(std::move(name), renderer, mappedInput) {}
|
: Activity(std::move(name), renderer, mappedInput) {}
|
||||||
void loop() override;
|
void loop() override;
|
||||||
void onExit() override;
|
void onExit() override;
|
||||||
|
bool preventAutoSleep() override { return subActivity && subActivity->preventAutoSleep(); }
|
||||||
|
bool skipLoopDelay() override { return subActivity && subActivity->skipLoopDelay(); }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -861,6 +861,8 @@ void EpubReaderActivity::renderScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!section) {
|
if (!section) {
|
||||||
|
loadingSection = true;
|
||||||
|
|
||||||
const auto filepath = epub->getSpineItem(currentSpineIndex).href;
|
const auto filepath = epub->getSpineItem(currentSpineIndex).href;
|
||||||
LOG_DBG("ERS", "Loading file: %s, index: %d", filepath.c_str(), currentSpineIndex);
|
LOG_DBG("ERS", "Loading file: %s, index: %d", filepath.c_str(), currentSpineIndex);
|
||||||
section = std::unique_ptr<Section>(new Section(epub, currentSpineIndex, renderer));
|
section = std::unique_ptr<Section>(new Section(epub, currentSpineIndex, renderer));
|
||||||
@@ -880,6 +882,7 @@ void EpubReaderActivity::renderScreen() {
|
|||||||
viewportHeight, SETTINGS.hyphenationEnabled, SETTINGS.embeddedStyle, popupFn)) {
|
viewportHeight, SETTINGS.hyphenationEnabled, SETTINGS.embeddedStyle, popupFn)) {
|
||||||
LOG_ERR("ERS", "Failed to persist page data to SD");
|
LOG_ERR("ERS", "Failed to persist page data to SD");
|
||||||
section.reset();
|
section.reset();
|
||||||
|
loadingSection = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -912,6 +915,8 @@ void EpubReaderActivity::renderScreen() {
|
|||||||
section->currentPage = newPage;
|
section->currentPage = newPage;
|
||||||
pendingPercentJump = false;
|
pendingPercentJump = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadingSection = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.clearScreen();
|
renderer.clearScreen();
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class EpubReaderActivity final : public ActivityWithSubactivity {
|
|||||||
bool pendingSubactivityExit = false; // Defer subactivity exit to avoid use-after-free
|
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 pendingGoHome = false; // Defer go home to avoid race condition with display task
|
||||||
bool skipNextButtonCheck = false; // Skip button processing for one frame after subactivity exit
|
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()> onGoBack;
|
||||||
const std::function<void()> onGoHome;
|
const std::function<void()> onGoHome;
|
||||||
|
|
||||||
@@ -55,4 +56,10 @@ class EpubReaderActivity final : public ActivityWithSubactivity {
|
|||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void onExit() override;
|
void onExit() override;
|
||||||
void loop() 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; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -57,4 +57,7 @@ class TxtReaderActivity final : public ActivityWithSubactivity {
|
|||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void onExit() override;
|
void onExit() override;
|
||||||
void loop() 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; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
// 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
|
// When an activity requests skip loop delay (e.g., webserver running), use yield() for faster response
|
||||||
// Otherwise, use longer delay to save power
|
// Otherwise, use longer delay to save power
|
||||||
|
|||||||
Reference in New Issue
Block a user