Mobile Development 11 min read

Analyzing Android TextView ANR Caused by getOffsetForHorizontal Loop Using Frida

This article investigates an Android ANR triggered by a while‑true loop in TextView's getOffsetForHorizontal, reproduces the issue on Pixel 2, explains how to extract trace files, compares Android Studio debugging with Frida dynamic hooking, and provides step‑by‑step instructions to reproduce and debug the bug.

Kuaishou Tech
Kuaishou Tech
Kuaishou Tech
Analyzing Android TextView ANR Caused by getOffsetForHorizontal Loop Using Frida

While eating noodles, the author was @‑mentioned in a group chat and decided to share a mysterious code snippet that later caused an ANR (Application Not Responding) on certain Android devices.

The issue was reproduced on a Pixel 2 (Android 8.1.0, WeChat 8.0.7) but not on a Redmi Note 3 (Android 5.0.2, WeChat 8.0.3). The author notes that most WeChat versions exhibit the problem, and the difference is due to the OS version.

To analyze the ANR, a trace file was collected. If the device is rooted, the file can be taken directly from /data/anr ; otherwise, it can be obtained via adb bugreport and extracted from the FS/data/anr directory.

Inspection of the trace suggested that the ANR originates from an infinite loop in nextSpanTransition , which is called from getOffsetToLeftRightOf inside android.text.TextLine (line 522). The relevant code contains a while (true) construct.

Two debugging approaches are discussed:

Using Android Studio to step through the code. This method requires the target app to be debuggable and the source version to match the device OS; otherwise, line numbers may not align.

Using Frida for dynamic hooking. Frida works even when the app is not debuggable or when AS debugging is inconvenient (e.g., system_server).

Frida setup steps:

Prepare a rooted device.

Download the appropriate frida-server from GitHub.

Push it to the device: adb push frida-server /data/local/tmp/frida-server

Make it executable: adb shell chmod 777 /data/local/tmp/frida-server

Start the server: adb shell /data/local/tmp/frida-server

Install Frida tools on the host: pip install frida

Write a hook script (e.g., anr.hook.js ) to intercept getOffsetBeforeAfter and nextSpanTransition .

Run the app and load the script: frida -U pkgName -l anr.hook.js

The hook captured method parameters, revealing that nextSpanTransition receives identical start and limit values (81), leading to a condition where spanLimit >= target can never be satisfied, thus causing the infinite loop.

The author explains why older Android versions (≤ 7.x) do not exhibit the bug: their implementation of getOffsetForHorizontal does not call Layout.getOffsetToLeftRightOf , avoiding the problematic code path.

A minimal reproducible demo is provided: a TextView containing a specially crafted Unicode string and a custom LinkMovementMethod override. Touching the TextView on affected devices triggers the ANR.

The article concludes that the bug stems from handling right‑to‑left Unicode characters in combination with Span logic, and suggests developers audit their usage of getOffsetForHorizontal to avoid similar crashes.

debuggingMobile DevelopmentAndroidANRFridaTextView
Kuaishou Tech
Written by

Kuaishou Tech

Official Kuaishou tech account, providing real-time updates on the latest Kuaishou technology practices.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.