dumpsys gfxinfo cannot see a SurfaceView's own GPU-drawn frames at all
(RUST.md's I5 box), so iris needs its own equivalent of Compose's
render-report button before item 3 of the recommendation can be decided
by a number. FrameReport (iris/core/src/render/frame_report.rs) records
each frame's wall time -- from render()'s redraw start to after
queue.submit + present() -- into a fixed 4096-entry ring, and reports
total frames, janky % (>16.7ms, gfxinfo's own budget), P50/P90/P99 and
the worst. Wired into AndroidUiState and android/view.rs's render(), and
exposed as two named controls ("Frame report", "Reset frame report") on
iris-android-app's transcript screen, logged under the crate's fixed tag
so a script can grep "iris frame report" the way transcript-bench.sh
greps "ai-app render report".
6 new unit tests for the ring/percentile math. cargo fmt/clippy/test
--workspace clean; cargo ndk (iris, transcript-ui, and
iris-android-app --features transcript-screen) all clean.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
5.3 KiB
5.3 KiB
Decisions taken for Iris to review
Short list of design choices made by the design agent without asking, so they can be judged and reversed later. Detail lives in RUST.md (and IRIS.md for iris API changes); this file is only the summary. Newest first. Items marked DEFERRED are ones the agent chose not to decide alone.
2026-09-05
- iris gets its own measured frame report, rather than waiting on a
dumpsys/gfxinfoanswer that cannot see aSurfaceView's GPU-drawn frames.iris_core::FrameReport(iris/core/src/render/frame_report.rs) times each frame's wall clock from the same pointrender()'s redraw starts to just afterqueue.submit+present()— the span Compose's own render report andgfxinfoboth count — into a fixed 4096-entry ring (no allocation per frame;report()is the only place that allocates, and only on a button tap). The report gives total frames, janky % over the same 16.7ms budgetgfxinfouses, P50/P90/P99 and the worst, plus a reset. Exposed the way the Compose app's copy-button report already is: two named controls ("Frame report", "Reset frame report") on the transcript screen, tappable by accessibility name viaui-trace, logging under this crate's fixedandroid_loggertag (iris-android-app) so a script can grep"iris frame report"the waytranscript-bench.shgreps"ai-app render report". The report's ownDisplayline says plainly that it measures up to thepresent()call returning, not GPU/compositor completion — wgpu'spresent()is not fenced against either, so presenting that span as "time to reach the screen" would be a measured-looking number that is actually inferred, which the standing UI rule forbids. ui-tracegains a hold-then-drag gesture, additive, inemulator-tools. Neither of its two existing actions can produce "hold stationary forLONG_PRESS, then move without lifting" —taphas no hold andswipe X1 Y1 X2 Y2 MSinterpolates motion across its whole duration from t=0. A new action presses, waits, then moves to a second point and releases as one continuous touch (rawsendevent/MotionEventinjection, extending whatever mechanism the existingswipealready uses), soDragArbiter's pan-vs-select rule (iris/src/sense.rs, already covered by 8 unit tests against a synthetic clock) can finally be driven on a real device instead of only in a test harness.- Touch drag on a transcript row follows Android's own rule: a vertical
drag pans the list immediately; a stationary press held 500 ms starts a
text selection which further dragging extends; a horizontal drag while
something is already selected extends that selection without the wait.
One
DragArbiterper list decides it (iris/src/sense.rs). Chosen over a "text layer always wins" or "list always wins" rule because either loses one of the two gestures a reader expects. - E4's desktop shape is a new
iris/desktop-appcrate: a winit window holdingtranscript-ui's screen beside a session list, talking to a realai-serverthroughclient-core. It enrols by pasting the sameaiapp://enroll?…link a phone scans (client-core::config::EnrolledServer) and keeps it owner-only under$XDG_CONFIG_HOME/ai-app-desktop/. The pinned CA is a path given on the command line, not baked in. Chosen so the phone and desktop share one enrolment format and no second one is invented. - I5's Android integration extends
iris-android-app(I2's shell) behind a Cargo feature (transcript-screen), rather than a third shell crate. That project already has the Gradle module, theIrisView/MainActivityJava, and the JNI registration; the only thing a second screen needs on top is a differentAndroidAppState, the same axistabs_ui::build/transcript_ui::buildalready vary along on the winit side.tabs-screen/transcript-screenare mutually exclusive and each pulls in only its own deps, so the plain tabs build (I2/I4) is untouched. - Order of remaining work, updated 2026-09-05: the two in-flight pieces and I5's Android integration are all done; next is giving iris its own frame-timing report so item 3 below can be decided by a number.
- DEFERRED — whether to commit to iris over Masonry for
ai-app. Updated 2026-09-05 with what's now known: iris's Android integration is built and confirmed working on a real device (real server, real scrolling, real touch-drag pan, tap-by-name accessibility — RUST.md's I5 box), while Masonry's own touch-scroll on Android was already found entirely absent (E2). What's still missing on both sides is a render-time number — not because iris doesn't work, but becausedumpsys gfxinfocannot see aSurfaceView's GPU-drawn frames at all, so thetranscript-bench.sh-style comparison this recommendation wanted produced a real number for Compose (8.96% janky, 99th percentile 150ms, same emulator/session) and none at all for iris. The choice in front of Iris: decide now on the structural-plus-functional case already made (iris works end-to-end where Masonry's scroll gesture doesn't exist at all on Android), or wait for iris to grow its own frame-timing instrumentation first so the comparison can be a number rather than a qualitative one. RUST.md's "Recommendation" item 3 has the full account.