Skip to content

fix(android): treat null-class password/email fields as English (#200)#207

Merged
jrywu merged 4 commits into
masterfrom
fix/200-null-class-forced-english
Jul 25, 2026
Merged

fix(android): treat null-class password/email fields as English (#200)#207
jrywu merged 4 commits into
masterfrom
fix/200-null-class-forced-english

Conversation

@jrywu

@jrywu jrywu commented Jul 25, 2026

Copy link
Copy Markdown
Member

Problem

A single Latin key tap in LINE's Add Friends → ID search field inserts the character twice (jjj) — but only from the Chinese keyboard, not LIME's English keyboard.

Root cause (confirmed by on-device trace)

Captured the field's real EditorInfo on a Samsung SM-A1760 (Android):

onStartInput inputType=0x90  class=0x0(NULL)  variation=0x90(VISIBLE_PASSWORD)  imeOptions=SEARCH

The field declares a VISIBLE_PASSWORD variation with a null input class (0x90) instead of the well-formed 0x91 (TYPE_CLASS_TEXT | VISIBLE_PASSWORD).

LIME's forced-English handling in initOnStartInput() is gated on TYPE_CLASS_TEXT, so this field fell through to the Chinese composing path: a Latin key went into a composing region (setComposingText) instead of an atomic commit, and LINE's editor duplicated the composed character. The English keyboard forces mEnglishOnly=true (commit-only, no composing region) → no duplication.

The trace also proved LIME dispatches exactly one onKey + one setComposingText per tap — no LIME-side double-dispatch/double-commit. The duplication is entirely tied to the composing region, which only the Chinese keyboard creates. (The earlier TYPE_TEXT_VARIATION_URI / issue-#74 hypothesis is refuted — the field is not URI.)

Fix

Add effectiveInputClass(): a null-class field carrying a forced-English text variation (password / visible-password / web-password / email / web-email) is reinterpreted as TYPE_CLASS_TEXT, so LIME's existing commit-only handling applies. Every other input type is returned unchanged — ordinary Chinese text fields still compose. This extends LIME's existing password/email policy to the malformed null-class shape, not new behavior.

Test

test_200_NullClassForcedEnglishVariationResolvesToText:

  • 0x90TYPE_CLASS_TEXT (RED without the fix: expected:<1> but was:<0>)
  • rest of the forced-English set covered; well-formed fields unchanged
  • a true null field stays null → composing preserved (guards against over-forcing)

Verified RED→GREEN on a Pixel 9 Pro API 37 emulator and the Samsung SM-A1760, and the fix confirmed on-device: the jj duplication is gone; the ID field now commits Latin directly like the English keyboard.

Notes / follow-ups

  • The investigation doc from PR Investigate confirmed Android LINE ID duplicate input (#200) #201 (docs/#200_ISSUE.md) predates this trace and concluded "need a device trace." That's now done; its URI/記憶中英模式問題 #74 focus should be superseded by this confirmed root cause.
  • Scope limit: this keys on the variation, so it fixes fields shaped like LINE's. If another app duplicates in a plain normal-text field, that composing is legitimate for Chinese and would be a separate issue (matching the reporter's vague "another app" hint).
  • Behavior note: in this field the user can still tap to switch to Chinese; because forced-English leaves mPredictionOn=false, that yields a candidates-only (no inline composing) state. Optional polish, not the reported bug.

🤖 Generated with Claude Code

jrywu and others added 4 commits July 26, 2026 00:25
A single Latin tap in LINE's Add-Friends ID-search field duplicated the character
("j" -> "jj") from the Chinese keyboard, but not from the English keyboard.

Root cause, confirmed by an on-device EditorInfo trace on a Samsung SM-A1760: the
field declares inputType=0x90 — a VISIBLE_PASSWORD variation with a null input
class (TYPE_NULL) instead of the well-formed 0x91 (TYPE_CLASS_TEXT|VISIBLE_PASSWORD).
LIME's forced-English handling in initOnStartInput() is gated on TYPE_CLASS_TEXT,
so this field fell through to the Chinese composing path: a Latin key was placed in
a composing region (setComposingText) instead of committed, and LINE's editor
duplicated the composed character. The English keyboard forces mEnglishOnly=true
(atomic commitText, no composing region), so it never duplicated.

Fix: add effectiveInputClass(), which reinterprets a null-class field carrying a
forced-English text variation (password/visible-password/web-password/email/
web-email) as TYPE_CLASS_TEXT, so the existing commit-only handling applies. Every
other input type is returned unchanged, so ordinary Chinese text fields still
compose. This extends LIME's existing password/email policy to the malformed
null-class shape rather than introducing new behavior.

Test: test_200_NullClassForcedEnglishVariationResolvesToText asserts 0x90 resolves
to TEXT (RED without the fix: expected 1 but was 0), the rest of the forced-English
set is covered, well-formed fields are unchanged, and a true null field stays null
(composing preserved). Verified RED->GREEN on a Pixel 9 Pro API 37 emulator and the
Samsung SM-A1760; the fix was confirmed on-device (no more duplication).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On-device EditorInfo trace (Samsung SM-A1760) shows LINE's ID-search field is
inputType=0x90 — VISIBLE_PASSWORD variation with a null input class — which slips
past initOnStartInput()'s TYPE_CLASS_TEXT-gated forced-English handling and takes
the Chinese composing path; LINE's editor duplicates the composed character.
Documents the trace evidence, the refuted URI/#74 and double-dispatch hypotheses,
the effectiveInputClass() fix, the RED->GREEN test, and on-device verification.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…forced-english

# Conflicts:
#	docs/#200_ISSUE.md
Independent review follow-ups:
- Add null-class WEB_PASSWORD and WEB_EMAIL_ADDRESS assertions so the test covers
  the whole forced-English set the code and doc claim, plus a negative case
  (NUMBER class with password-like variation bits stays NUMBER) proving the
  reroute is gated on class==NULL, not on the variation bits.
- docs/#200_ISSUE.md: LINE is a closed app, so its editor-side duplication of the
  composing region was not directly instrumented. Tighten the "confirmed by trace"
  wording to state LIME's side is traced and the host duplication is inferred and
  confirmed by the fix removing the "jj".

Test GREEN on a Pixel 9 Pro API 37 emulator and the Samsung SM-A1760.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jrywu
jrywu merged commit f57cca9 into master Jul 25, 2026
@jrywu
jrywu deleted the fix/200-null-class-forced-english branch July 25, 2026 16:49
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.

1 participant