Skip to content

Release 1.0.0 (part 2): typing in every environment, crash and freeze resilience - #117

Merged
Slacker-LLC merged 13 commits into
mainfrom
release/1.0.0
Oct 2, 2026
Merged

Slacker-LLC merged 13 commits into
mainfrom
release/1.0.0

Conversation

@Slacker-LLC

Copy link
Copy Markdown
Owner

Typing in every environment, and surviving the ones that go wrong: the second half of 1.0.0 (the first half is #114, already on main). It supersedes #116 (same commits rebased onto main) and records the release signing certificate fingerprint, so the first release is checked against the key in the repository secrets.

Found by running the keyboard through real environments

  • Landscape went fullscreen. The framework default hides the app's own editor behind an unthemed copy of the field. onEvaluateFullscreenMode is now false: the keyboard is a bottom panel in every orientation.
  • Rows were clipped in landscape, on tablets and foldables. Content-box padding and row widths were applied from onSizeChanged, to views laid out later in the same pass; their requestLayout() calls are dropped (each view clears its force-layout flag when it finishes laying out), so rows kept the full window width inside the clamped box. Geometry is now applied in onMeasure, before children are measured.
  • 200% system font broke key labels ("m" became an ellipsis, "中/英" lost a glyph). Key labels follow the system font up to 1.3x; function labels keep autosizing.
  • TYPE_NULL editors (terminals, games, remote desktops): Backspace did nothing, because their dummy BaseInputConnection answers true to deleteSurroundingText and removes nothing. They now start in English, get each letter as a real key event, and delete with key events. Date/time fields start on digits.
  • No physical keyboard support: letters reached the app as Latin text. In 26-key Chinese mode they now compose pinyin (space, 1-9, Enter, Esc, ', full-width punctuation; shortcuts and capitals go to the app).

Crashes, freezes, conflicts

  • A failing typing handler is contained (recorded without typed text, composition dropped) instead of killing the keyboard.
  • Crash history from Java crashes, native crashes and ANRs (Android 11+ exit reasons); three in ten minutes start safe mode (no librime, no voice preload). The About screen can copy the diagnostics or leave safe mode.
  • librime start marker with escalation: clear compiled data, set the user dictionary aside, skip native. A start killed by the user or system is not counted.
  • Media volume muted for voice input is restored after an unclean exit and by a two-minute watchdog.
  • Huge commits are chunked below the Binder limit; the lexicon and nine-key decoder are built off the main thread; Backspace no longer makes three synchronous round trips into the app when the editor reported a collapsed cursor.
  • Nine-key left rail: one character's pinyin per item, as Baidu and rime-t9-shiyin do it.

Verification

Check Result
Unit tests, lint, assemble pass (plus 9 crash-resilience, 12 physical-keyboard, 6 editor/gateway tests)
Instrumented suite, API 36 emulator 102 tests, 0 failures, 2 skipped (assumeTrue on API level)
scripts/display_matrix_regression.py (11 environments) 11/11, fails on the unfixed build
scripts/core_regression.sh 19/19, including 037 (one pinyin per character), 038 (injected failure), 040-043 (physical keyboard)
New regression tests fail without their fixes checked for the layout and font tests

docs/COMPATIBILITY.md lists every environment, how it is handled and verified, and what is not covered (nine-key with a physical keyboard, candidates when the keyboard panel is hidden, OEM differences on real phones).

CI now also runs the instrumented suite on API 26 and 34 (informational; the release gate still requires 29 and 31), so a failure there is a finding rather than a regression.

🤖 Generated with Claude Code

Slacker-LLC and others added 10 commits October 2, 2026 13:50
… system fonts

Found by running the live keyboard through a display matrix instead of only the
default portrait phone:

- Landscape no longer enters fullscreen "extract" mode (onEvaluateFullscreenMode
  = false). By default the framework hid the app's own editor behind an
  unthemed copy of the field; chat, search and form typing disappeared.
- Content-box geometry (paddings, row widths) is now applied in onMeasure,
  before the children are measured. It used to be applied from onSizeChanged,
  i.e. to views that are laid out later in the same pass; their own
  requestLayout() calls are dropped because each view clears its force-layout
  flag when it finishes laying out, so the rows kept the full window width
  inside a clamped content box and were clipped (landscape, tablets, foldables).
  A deferred relayout flags the changed containers for late callers.
- Key labels follow the system font only up to 1.3x and the autosize of function
  labels survives applyMainTextScale. At 200% "m" became an ellipsis and "中/英"
  lost a glyph.

Tests: DisplayEnvironmentInstrumentedTest (content box and label fit across
layouts and font scales; both fail without these fixes), and
scripts/display_matrix_regression.py, which drives the real IME through 11
environments and asserts bottom-panel mode plus every key inside the window.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Commercial and open-source nine-key keyboards (Baidu, rime-t9-shiyin, iOS) let
the user choose the pinyin of one character at a time: the left column holds
the syllables for the next character, a tap fixes it and the list moves on.
The rail listed whole readings (ni'hao) for short input, which made one tap
decide the spelling of several characters. It now always lists first syllables.

Unit tests follow; core_regression case 037 types 64426, picks ni, then hao,
then space and expects 你好. docs/NINE_KEY_REFERENCE.md and the 1.0.0 notes
describe the new behaviour.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Both were built in onCreate on the main thread (about 0.3 s on a fast host) at
every cold start. The service starts with an empty pipeline and swaps in the
real one when the background thread is done; Rime supplies candidates meanwhile.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- CrashGuard records crashes locally (types and frames only, never typed text),
  folds native crashes and ANRs from Android's exit history into a crash loop
  counter, and three in ten minutes put the next start in safe mode (no librime,
  no voice preload) so the user can keep typing.
- A failing typing handler is contained: it is recorded, the half-finished
  composition is dropped and the keyboard carries on instead of being replaced
  by another keyboard. Debug command fail-next injects one (core_regression 038).
- Librime startup leaves a marker until the engine proves itself. A marker left
  by a start that died natively escalates: clear compiled data, set the user
  dictionary aside, then skip the native engine. A start merely killed by the
  user or system is not counted (Android 11+ exit reasons).
- Media volume muted for voice input is persisted and restored on the next start
  if the process dies mid-recording, and a watchdog restores it after two minutes
  (instrumented test).
- Huge commits (pasting megabytes) are chunked below the Binder limit.
- The lexicon and nine-key decoder are built off the main thread (they cost
  about 0.3 s on every cold start).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…er in the entry activities

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… handling

- TYPE_NULL editors (terminals, games, remote desktops) start in English,
  receive each letter as it is typed, and are edited with key events: their
  InputConnection is normally BaseInputConnection in dummy mode, where
  deleteSurroundingText answers true and removes nothing, so Backspace did
  nothing there. Pinyin still composes if the user switches to it.
- Date and time fields (TYPE_CLASS_DATETIME) start on digits.

Unit tests cover the editor kinds and the key-event paths.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
On tablets, foldables with a keyboard cover, Chromebooks, desktop mode and the
emulator, letters used to reach the app as plain Latin text. In the 26-key
Chinese mode they now compose pinyin: space picks the first candidate, 1-9 pick
a candidate, Enter keeps the typed pinyin, Esc cancels, ' separates syllables,
and , . ? ! ; : ( ) give full-width punctuation (after a digit , . : stay ASCII).
Ctrl/Alt/Meta shortcuts, capitals and every other key go to the app unchanged.
HardwareKeyPolicy is pure and unit-tested; core_regression 040-043 drive real
key events on the emulator.

docs/COMPATIBILITY.md lists every environment the keyboard handles, how, and how
it is verified, and what is still not covered.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Informational like the others; the release gate still requires 29 and 31.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…own collapsed

Deleting asked the app for the selected text and the extracted text before every
single-character delete: three synchronous Binder calls, each of which waits as
long as a slow or stuck app takes. Once the editor itself has reported a
collapsed cursor (onUpdateSelection, not the start-up values) there is no
selection to ask about.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The first release is verified against the key in the repository secrets too: the
build fails if the signing certificate differs from this SHA-256.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Slacker-LLC and others added 3 commits October 2, 2026 13:59
Decided by the owner. The APK ships Rime Ice dictionaries that are GPL-3.0-only;
licensing the project the same way leaves no question about how the dictionary
data and the program relate when the APK is distributed, and every other bundled
component (BSD, Apache-2.0, MIT) is compatible. LICENSE is the official text.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found by the new API 26 job: the two "P+" code-point deletion tests asserted
unconditionally although the gateway correctly falls back to UTF-16 deletion
below API 28, and the clipboard test created a ClipboardManager on a thread
without a Looper, which API 27 and below refuse. No product defect.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@Slacker-LLC
Slacker-LLC merged commit e31d7f3 into main Oct 2, 2026
7 checks passed
@Slacker-LLC
Slacker-LLC deleted the release/1.0.0 branch October 2, 2026 17:34
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