Skip to content

fix: defer focused input layout sync out of synchronous onStart dispatch - #1576

Merged
kirillzyusko merged 2 commits into
kirillzyusko:mainfrom
AhmedAlAmawi:fix/defer-focused-input-layout-sync
Aug 3, 2026
Merged

fix: defer focused input layout sync out of synchronous onStart dispatch#1576
kirillzyusko merged 2 commits into
kirillzyusko:mainfrom
AhmedAlAmawi:fix/defer-focused-input-layout-sync

Conversation

@AhmedAlAmawi

Copy link
Copy Markdown
Contributor

📜 Description

Moves the layoutObserver?.syncUpLayout() call out of the synchronous onStart dispatch and flushes it in flushPendingStartEvent() instead — right before the deferred Start event, so the original layout → start event order is unchanged. The resize branch (isResizeHandledInCallbackMethods) keeps its synchronous sync, so its behavior is untouched.

💡 Motivation and Context

Fixes #1575.

#1461 deferred the Start transition event out of the dispatchWindowInsetsAnimationStart window because Reanimated processes it synchronously on the UI thread, and a synchronous Fabric mutation there can cancel a pending IME insets controller before AOSP calls listener.onReady — AOSP checks isCancelled only before dispatching onStart and never re-checks it afterwards (InsetsController.startAnimation, android16-release ~L2151).

syncUpLayout() still dispatches FocusedInputLayoutChangedEvent through that same window and the same Reanimated-synchronous channel (useReanimatedFocusedInput / KeyboardAwareScrollView). On Android 16+ the victim can be ImeBackAnimationController (predictive back IME dismiss), which starts its post-commit ValueAnimator inside onReady and crashes with IllegalStateException: Can't change insets on an animation that is cancelled on the first animator frame — observed in production on 1.21.14, which already includes #1461. Full stack and AOSP analysis in #1575.

📢 Changelog

Android

  • deferred FocusedInputLayoutChangedEvent dispatch from onStart to the pending-start-event flush (first onProgress/onEnd), preventing reentrant cancellation of a pending IME insets controller during predictive back dismissal

🤔 How Has This Been Tested?

📝 Checklist

  • CI successfully passed
  • I added new mocks and corresponding unit-tests if library API was changed (N/A — no API change)

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

📊 Package size report

Current size Target Size Difference
334006 bytes 334006 bytes 0 bytes 📉

@kirillzyusko kirillzyusko self-assigned this Aug 3, 2026
@kirillzyusko kirillzyusko added 🤖 android Android specific 🎯 crash Library triggers a crash of the app focused input 📝 Anything about focused input functionality labels Aug 3, 2026

@kirillzyusko kirillzyusko left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good and e2e tests passed, so it should be all good. I left few minor comment, if you address them we can merge this PR.

I have one question - did you experience new crash yourself or in Sentry/crashlytics? Did crash gone after these changes?

@AhmedAlAmawi

Copy link
Copy Markdown
Contributor Author

did you experience new crash yourself or in Sentry/crashlytics? Did crash gone after these changes?

We saw it in our production crash reporting — Pixel 8, Android 16, predictive back gesture on a screen using KeyboardAwareScrollView, on a build that was already running 1.21.x with the #1461 deferral in place. It's a low-frequency crash for us (we never managed a deterministic local repro), so I can't give a statistically meaningful before/after yet — the root cause came from tracing the one remaining synchronous dispatch (syncUpLayout) inside onStart against the AOSP InsetsController source rather than from reproducing it on a device.

We're shipping this patch in our next release, so I'll follow up on #1575 if it ever shows up again in the wild.

@kirillzyusko

Copy link
Copy Markdown
Owner

We're shipping this patch in our next release

Do you have an ETA when you ship next release with patch and when you can say whether the issue is reproducible or not? 👀

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor
  1. Missing Layout Observer Call in onApplyWindowInsets
    Why: Removing layoutObserver?.syncUpLayout() may prevent proper UI updates when keyboard size changes, leading to layout issues.
    Fix: Re-add the call to ensure layout is synced after applying window insets.

  2. Multiple syncUpLayout Calls Potentially Leading to Redundant Updates
    Why: Adding multiple calls might cause unnecessary recalculations or threading issues.
    Fix: Review and consolidate syncUpLayout invocations to avoid redundancy and potential race conditions.

LGTM

@AhmedAlAmawi

Copy link
Copy Markdown
Contributor Author

Our next native build goes out this Wednesday (Aug 5) — we're applying this change as a local patch on 1.22.2 so it doesn't have to wait for an upstream release. Store rollout usually takes about a week to reach most of our users after that.

On reproducibility: it's a very low-frequency crash for us (single occurrences over roughly a month of production traffic), so I'd expect a meaningful read in about 3–4 weeks of the patched build being live. I'll report back on #1575 either way — whether it's gone or it resurfaces.

@kirillzyusko

Copy link
Copy Markdown
Owner

Okay, let's merge this PR then 👍

I think it has a minor impact (in terms of dispatching order, because we already defer onStart event) and it's a logical continuation of #1461

@kirillzyusko
kirillzyusko merged commit 9e63b74 into kirillzyusko:main Aug 3, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🤖 android Android specific 🎯 crash Library triggers a crash of the app focused input 📝 Anything about focused input functionality

Projects

None yet

2 participants