Skip to content

RUMS-5996: Fix ANR in old-arch SR text mapper #1296

Merged
jonathanmos merged 3 commits into
developfrom
jmoskovich/rums-5996/android-old-arch-text-style-resolution
Jun 2, 2026
Merged

RUMS-5996: Fix ANR in old-arch SR text mapper #1296
jonathanmos merged 3 commits into
developfrom
jmoskovich/rums-5996/android-old-arch-text-style-resolution

Conversation

@jonathanmos
Copy link
Copy Markdown
Member

@jonathanmos jonathanmos commented Jun 1, 2026

What does this PR do?

Fixes an ANR on Android on the React Native old architecture caused by the Session Replay text mapper blocking the UI thread on every TextView in a snapshot.

Root cause: LegacyTextViewUtils fetched RN text properties (font family, size, color) by posting a runnable to mqt_native_modules and synchronously blocking the UI thread on a CountDownLatch for up to 5 seconds via ShadowNodeWrapper.getShadowNodeWrapper. If mqt_native_modules was busy (e.g. mid-UIManagerModule.onBatchComplete / Yoga layout — the very batch whose redraw triggered the snapshot), the posted runnable queued behind that work and the UI thread waited. With even a handful of TextViews on screen, the cumulative wait exceeded the 5-second input-dispatch deadline and the system fired an ANR.

Fix: Removed ShadowNodeWrapper entirely from the old-arch text mapper. All three text properties are now read directly off the TextView, matching what FabricTextViewUtils already does:

Font size: view.textSize (unchanged, was already correct)
Text color: read from ForegroundColorSpan on the view's Spanned text (RN old arch encodes color as a span, not via TextView.setTextColor())
Font family: read from CustomStyleSpan via Class.forName + reflection (RN old arch applies font family to TextPaint at draw time via this span, never via TextView.setTypeface())
FabricTextViewUtils (new architecture) is not affected — it already reads directly from the TextView with no cross-thread calls.

Motivation

What inspired you to submit this pull request?

Additional Notes

Anything else we should know when reviewing?

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests
  • Make sure you discussed the feature or bugfix with the maintaining team in an Issue
  • Make sure each commit and the PR mention the Issue number (cf the CONTRIBUTING doc)
  • If this PR is auto-generated, please make sure also to manually update the code related to the change

@datadog-prod-us1-3

This comment has been minimized.

@jonathanmos jonathanmos force-pushed the jmoskovich/rums-5996/android-old-arch-text-style-resolution branch from 746e751 to e83f6e7 Compare June 1, 2026 13:06
@jonathanmos jonathanmos force-pushed the jmoskovich/rums-5996/android-old-arch-text-style-resolution branch from e83f6e7 to db7dfe6 Compare June 1, 2026 13:11
@jonathanmos jonathanmos changed the title RUMS-5996: Fix ANR in old-arch SR text mapper by removing synchronous… RUMS-5996: Fix ANR in old-arch SR text mapper Jun 1, 2026
@jonathanmos jonathanmos marked this pull request as ready for review June 1, 2026 18:51
@jonathanmos jonathanmos requested a review from a team as a code owner June 1, 2026 18:51
Copilot AI review requested due to automatic review settings June 1, 2026 18:51
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses an ANR in React Native old architecture Session Replay text mapping by removing the UI-thread-blocking shadow node resolution path and instead deriving text styling directly from the TextView (via Spanned spans and typeface fallback), aligning behavior more closely with the existing Fabric/new-arch mapper.

Changes:

  • Removed ShadowNodeWrapper (and related reflection/UIManager shadow-node access) from the legacy text mapper to avoid blocking the UI thread.
  • Updated LegacyTextViewUtils to resolve font family (via CustomStyleSpan reflection), font size (via AbsoluteSizeSpan / TextView.textSize), and text color (via ForegroundColorSpan) directly from the TextView.
  • Refactored and expanded JVM tests to validate the new span/typeface-based resolution behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
packages/react-native-session-replay/android/src/test/kotlin/com/datadog/reactnative/sessionreplay/utils/text/TextViewUtilsTest.kt Updates tests to cover span/typeface-based style resolution and removes shadow-node based setup.
packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/text/TextViewUtils.kt Removes legacy ReflectionUtils dependency and updates factory creation for legacy implementation.
packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/utils/text/LegacyTextViewUtils.kt Replaces shadow-node lookups with direct TextView/Spanned inspection and reflection on CustomStyleSpan.
packages/react-native-session-replay/android/src/main/kotlin/com/datadog/reactnative/sessionreplay/ShadowNodeWrapper.kt Deletes the blocking shadow-node wrapper implementation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@jonathanmos jonathanmos merged commit a45be88 into develop Jun 2, 2026
11 checks passed
@jonathanmos jonathanmos deleted the jmoskovich/rums-5996/android-old-arch-text-style-resolution branch June 2, 2026 06:53
@sbarrio sbarrio mentioned this pull request Jun 2, 2026
4 tasks
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.

3 participants