Skip to content

feat(session): tile discard (freeze/thaw) + audio-mute + frame-cadence ops#27

Merged
wenkaifan0720 merged 2 commits into
mainfrom
feat/tile-freeze-thaw
Jul 24, 2026
Merged

feat(session): tile discard (freeze/thaw) + audio-mute + frame-cadence ops#27
wenkaifan0720 merged 2 commits into
mainfrom
feat/tile-freeze-thaw

Conversation

@wenkaifan0720

Copy link
Copy Markdown
Collaborator

What

Adds session-level discard (freeze/thaw) to flutter_cef, plus two
lower-cost levers, so a host can reclaim a hidden tile's Chromium footprint
without losing its on-screen frame.

  • freeze() — tears down a session's browser (and, when it was the
    profile's last live browser, the whole cef_host process tree) while the
    consumer-held CVPixelBuffer keeps serving the last painted frame (the
    IOSurface is a kernel object that survives the producer exit).
  • thaw({url, html}) — recreates a browser onto the same session/texture
    through the normal create path, reusing the C2 re-home attach (with a fix for
    its latent stale-presentCount bug).
  • setAudioMuted(bool) (op 0x3a) and setFrameInterval (op 0x3b) —
    cheaper levers for tiles that should stay live but quiet/slow.

Wire protocol bumps v4 → v5.

Why

Each webview tile is its own renderer tree; a busy canvas of them is the memory
ceiling. Discard reclaims a hidden tile's RSS while the texture stays visually
intact, and thaw restores it on the next visible edge.

Validation

Consumed live from work_canvas (co-dev path override). A board of webviews:
baseline ~2.1 GB / 17 procs → after discard ~0.9 GB / 7 procs, whole host tree
exiting on the last freeze; switching back thaws cleanly. See the companion
work_canvas PR for the full harness + a --assert regression guard.

Landing note

Because this bumps the wire protocol, the consumer must make pin-cef to this
commit and make publish-cef-host so a content-hash-matched prebuilt exists
before the pin flips — otherwise agent_ui/cefWebview tiles freeze/blank silently.

🤖 Generated with Claude Code

wenkaifan0720 and others added 2 commits July 23, 2026 20:21
freeze() tears down one session's native browser — and, when it was the
profile's last live browser, the whole cef_host process tree — while the
FlutterTexture keeps serving the last painted frame (the consumer-held
CVPixelBuffer retains the producer's IOSurface, a kernel object that
survives the producer's exit). thaw() recreates a browser onto the SAME
session/texture through the normal create pacer + establishment
watchdogs, reusing the C2 re-home attach() path; the frozen frame shows
until the new first paint adopts, so there is no flash.

detachForFreeze() resets the establishment counters (firstPresentSeen /
presentCount / lastPresentNs / livenessNudgedAt) so the thawed browser
reads as a FRESH establishment to the pacer and first-present watchdog —
a stale presentCount would pin the pacer slot until the timeout backstop
and repeat-fire paintStalled.

Side levers, policy left to the consumer:
- setAudioMuted (kOpSetAudioMuted 0x3a): a hidden AND muted page regains
  Chromium's intensive wake-up throttling (audible pages are exempt).
- setFrameInterval (kOpSetPumpInterval 0x3b): per-slot visible
  begin-frame cadence, clamped [8, 250]ms — 33ms halves an unengaged
  tile's paint/blit CPU.

kCefHostProtocolVersion 4 -> 5 (new ops; the opReady handshake refuses
skewed prebuilts).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The agent_ui discard path regenerates its document from host-side state,
so thaw needs the same html->data-URL entry create/loadHtml have (html
wins over url, mirroring create). Purely Dart-side: converts to a data:
URL and rides the existing thawSession url param — no native change.

Without this, a consumer that froze an authored-document session can only
thaw by url, losing its live state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@wenkaifan0720
wenkaifan0720 merged commit 956e8fc into main Jul 24, 2026
2 checks passed
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.

1 participant