Description
NEW UPDATE: we have now released patch releases containing the second wave of fix for:
- https://github.com/facebook/react-native/releases/tag/v0.69.10
- https://github.com/facebook/react-native/releases/tag/v0.70.9
- https://github.com/facebook/react-native/releases/tag/v0.71.7
- https://github.com/facebook/react-native/releases/tag/v0.68.7
UPDATE: we have now released a patch release containing the first mitigation for all the supported versions of React Native plus 0.68 (since it's still used by a significant number of users):
- https://github.com/facebook/react-native/releases/tag/v0.68.6
- https://github.com/facebook/react-native/releases/tag/v0.69.8
- https://github.com/facebook/react-native/releases/tag/v0.70.7
- https://github.com/facebook/react-native/releases/tag/v0.71.2
Please upgrade to those versions and report back here if it helps! We are still planning to do further investigation, but don't expect any new releases concerning this topic for at least a couple weeks (unless something unexpected happens).
There have been repeated and persistent signals of ANRs (hangs) when typing into a multiline TextInput on Samsung phones. This is most reported by using the out-of-the-box keyboard provided by Samsung One UI 5. We have been able to locally reproduce the hangs on two separate Galaxy S22 devices. Most devices will not be as fast as the ones we have tested on.
Impact
The issue presents as repeated hangs or ANRs when typing into a TextInput which has a large amount of text. It is specific to the Samsung soft keyboard, and does not reproduce when using other keyboards like GBoard on the same device. There are a different set of TextInputs where we have confirmed impact depending on whether Fabric is enabled or disabled.
Fabric enabled
Both controlled and uncontrolled TextInputs are impacted.
Fabric disabled
Controlled TextInputs and uncontrolled TextInputs which set an initial value via child are impacted.
Root causing
Root causing the issue focused on:
- Locally profiling the hang under different scenarios
- Examining which span differences create the hang
- Reproducing the issue outside of React Native
Profiling
We saw similar results to the trace already shared in #35590. A Java sampling profiler shows the process com.samsung.android.honeyboard
has a very long running frame, delivering input.
This triggers code on the main thread, in the app process, where we see a hang happen while committing a text change from the IME to the underlying Spannable backing the EditText. The hang happens in an event handler which has subscribed to changes to the underlying text. The long-running work seems to be laying out the text.
Because the hang happens in response to an edit to the underlying Spannable, investigation focused on the Spannable content differences in scenarios which created ANRs vs not.
Spannable differences between hang/no hang
We examined typing into the below example, which may hang on Fabric but not Paper:
<TextInput multiline={true} />
Grammarly annotations were present as SuggestionSpan
spans on both platforms. On Fabric but not paper there was the presence of AbsoluteSizeSpan
spans, which set the font size within the text. This is akin to setting <span style=”font-size: 12px”}>Text</span>
within a browser.
When we stubbed out platform code in React Native which set an AbsoluteSizeSpan
, that example along with another previously hanging example would no longer hang. The hang was possible to trigger in an uncontrolled TextInput with a short string like “Text Here” as a child, so we attempted to repro the logical extreme, where we add a single span setting font size to the TextInput.
Reproducing outside of React Native
We discovered that adding even a single inclusive span (specifically setting font size) is enough to create hangs. This can reproduced by:
- Adding an
EditText
with aninputType
oftextMultiLine
. - Adding an inclusive span setting font size: E.g.
str.setSpan(new AbsoluteSizeSpan(55), 0, string.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE)
- Pasting a large amount of text then starting to type.
We were able to create a repro for this on top of a template Android application. The issue only happens when using the Samsung keyboard.
reproducervideo.mp4
Grammarly annotations are not shown locally when changing the appId and namespace of the repro to This only happened on 1/2 devices, so it's possible there might be some setting or association that wasn't fresh.com.facebook.katana
(the ID of the Facebook app). This implies the Facebook app may be being special-cased, contributing to the lack of internal signal on the issue.
Remediation
While the underlying issue seems to be outside of React Native, the issue still has a real-world effect on our users. We are starting the process to mitigate the issue by working to notify Samsung. This issue has already shown signs of impacting the Android app ecosystem outside of React Native and the ability to set spans with formatting like font size is a fundamentally important part of the platform.
We hope this issue will be addressed in a future update from Samsung, but this does not address the already-present impact of the issue. A potential mitigation which we are exploring is whether React Native could avoid adding AbsoluteSizeSpan (or formatting spans in general) in more common cases.
There have been previously discovered workarounds for the issue, such as setting keyboardType
to visible-password
. We recommend against preemptively using these workarounds, due to impact on UX and accessibility.