Files
virtual-controller/remote-client-android/FEEDBACK_STUTTER_BUG.md
T
Paul Lipscomb 6f66a5db64 Move feedback stutter bug report to android folder
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-07-30 19:14:00 -05:00

78 lines
4.1 KiB
Markdown

# Android Feedback Widget Stutter Bug
## Summary
When the Android tablet app receives high-frequency network feedback updates (60hz timecode from desktop), the feedback widget AND the fader control stutter and become unresponsive. Works perfectly on iOS and desktop apps at the same 60hz update rate.
## Symptoms
- Feedback widgets (showing timecode, etc.) display with visible frame drops/stutter
- Fader touch input becomes intermittent and unresponsive while feedback updates are happening
- Stutter correlates directly with network update frequency — higher frequency = worse stutter
- **But:** When feedback updates are disabled entirely, fader moves smoothly
## What Works Fine
- **iOS:** Receives and displays 60hz feedback updates smoothly while handling touch input perfectly
- **Desktop (PyQt):** No performance issues at all with high-frequency updates
- **Android:** Fader drag is smooth and responsive when feedback updates are NOT happening
## Current Code Flow
1. WebSocket listener receives message on background thread
2. `ArrangeFunctionsWebSocket.handleWidgetFeedback()` processes the JSON
3. Calls `vc.runOnUiThread()` to queue update on main thread
4. Inside runOnUiThread: calls `widget.setTextFromNetwork(text)`
5. `FocusFeedbackWidgetView.setTextFromNetwork()`:
- Checks if text changed (skip if identical)
- Calls `setText(text)`
- ~~Was calling `requestFit()` (recalculates widget size) — REMOVED~~
## What We've Tried
1.**Removed requestFit() calls** — was recalculating widget dimensions 60x/sec, expensive
2.**Added text equality check** — only call setText() if text actually changed
3.**Removed requestFit() from setText()** — no longer triggers layout recalculation
4.**Tried Handler-based batching** — user said to revert immediately (didn't help)
Result: **No improvement.** Still stutters.
## Hypothesis: setText() Itself is Expensive
Even a simple `setText()` call triggers Android's view measurement/layout system:
- Measure text width/height
- Recalculate layout
- Trigger redraw
At 60hz, this is apparently enough to starve the main thread of time to process touch events.
**But this seems wrong.** TouchOSC works fine on Android with similar high-frequency updates.
## Investigation Needed
1. **Is it actually setText()?** — Test: completely disable feedback updates (don't call setTextFromNetwork at all). If fader still stutters, problem is elsewhere.
2. **Is flashCard() the culprit?**`handleWidgetFeedback()` calls `flashCard(uid)` after setText. That triggers activity ring animation. Could that be the expensive part?
3. **Is there something else?** — Maybe the problem is in the WebSocket thread itself, not the UI updates?
4. **Custom Canvas View?** — TouchOSC might use custom Canvas-based rendering instead of TextViews. Maybe we need to do the same.
## Architecture Difference: iOS vs Android
**iOS:**
- Render server is completely separate from main thread
- Touch events handled by separate high-priority daemon, never blocked by UI work
- Core Animation batches updates intelligently
**Android:**
- Single main thread handles both touch events AND UI updates
- If main thread is busy with view measurement/layout, touch events get dropped
- No separation between UI work and input handling
## Files Involved
- `ArrangeFunctionsWebSocket.java` — handleWidgetFeedback() method (line ~290)
- `FocusFeedbackWidgetView.java` — setTextFromNetwork() method (line ~143)
- `ArrangeCardView.java` — flashCard(), refitFeedback() methods (for context on what happens after setText)
## Next Steps for Fable
1. **First:** Test if disabling feedback updates entirely makes fader smooth (confirm setText is actually the problem)
2. **If still stutters:** Look at flashCard() and activity ring animation
3. **If not setText/flashCard:** Investigate WebSocket thread behavior
4. **If those aren't it:** Prototype a custom Canvas-based feedback view as a replacement for TextView
## Key Question
Why does TouchOSC handle this fine on Android if TextView updates are so expensive? Either:
- They don't update as frequently as 60hz
- They use a custom view for rendering
- They've optimized something we haven't found yet