fix(engine): safe-area insets never re-polled after app resume (stale on fold/unfold) #116

Closed
opened 2026-07-06 19:18:48 +00:00 by funman300 · 0 comments
Owner

Severity: Medium-High (Android correctness)

Problem

rearm_on_resumed (solitaire_engine/src/safe_area.rs) resets SafeAreaPollTries to 0 on AppLifecycle::WillResume so that refresh_insets "re-queries JNI in the frames immediately after the app returns to the foreground."

But refresh_insets early-returns whenever the cached insets are already populated:

if poll.0 >= MAX_TRIES || insets.is_populated() {
    return;
}

Once insets resolve on first launch, insets.is_populated() is permanently true, so the poll-counter reset on resume is a no-op — JNI is never queried again for the lifetime of the process.

Consequence

If the system insets change while the app is backgrounded (rotation, fold/unfold on a foldable, gesture-nav ↔ 3-button nav switch, split-screen), the layout keeps the stale insets until the app is killed and relaunched. This directly affects the Galaxy Fold 7 fold/unfold flow.

Also

The doc comment above rearm_on_resumed (around line 193) still describes the old behaviour: "resets both SafeAreaPollTries and SafeAreaInsets to zero". The code intentionally no longer zeroes the insets (to avoid the resume double-flash), so the comment is stale and contradicts the later comment on the function itself.

Suggested fix

  • Track a "resumed" flag (or compare a fresh JNI reading against the cache) so refresh_insets re-polls for a few frames after resume even when insets are populated, updating only when the value actually differs — preserving the no-flash behaviour.
  • Update the stale doc comment at ~line 193.

Found during scripted repo review (todoctx/peek audit), 2026-07-06.

**Severity: Medium-High (Android correctness)** ## Problem `rearm_on_resumed` (`solitaire_engine/src/safe_area.rs`) resets `SafeAreaPollTries` to 0 on `AppLifecycle::WillResume` so that `refresh_insets` "re-queries JNI in the frames immediately after the app returns to the foreground." But `refresh_insets` early-returns whenever the cached insets are already populated: ```rust if poll.0 >= MAX_TRIES || insets.is_populated() { return; } ``` Once insets resolve on first launch, `insets.is_populated()` is permanently true, so the poll-counter reset on resume is a **no-op** — JNI is never queried again for the lifetime of the process. ## Consequence If the system insets change while the app is backgrounded (rotation, fold/unfold on a foldable, gesture-nav ↔ 3-button nav switch, split-screen), the layout keeps the stale insets until the app is killed and relaunched. This directly affects the Galaxy Fold 7 fold/unfold flow. ## Also The doc comment above `rearm_on_resumed` (around line 193) still describes the *old* behaviour: "resets both `SafeAreaPollTries` and `SafeAreaInsets` to zero". The code intentionally no longer zeroes the insets (to avoid the resume double-flash), so the comment is stale and contradicts the later comment on the function itself. ## Suggested fix - Track a "resumed" flag (or compare a fresh JNI reading against the cache) so `refresh_insets` re-polls for a few frames after resume even when insets are populated, updating only when the value actually differs — preserving the no-flash behaviour. - Update the stale doc comment at ~line 193. Found during scripted repo review (todoctx/peek audit), 2026-07-06.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: funman300/Ferrous-Solitaire#116