Harden Android accessibility, localization and startup (#105)
Implement independent hardening and regression coverage. Keep #105 open for final feature and environment coverage after #106–#110; document the completion boundary and resume order.
This commit is contained in:
1 parent
43f660ace3
commit
6669b77f4e
55 files changed
+24445
-296
No files matched your search
@@ -0,0 +1,108 @@
|
||||
# Android hardening
|
||||
|
||||
The Android presentation layer uses resource strings for Kotlin-owned notices,
|
||||
action labels, counts, and durations. Rust-owned presentation text remains opaque:
|
||||
frontends do not parse or translate it. Repeated editor actions include the field
|
||||
label, and hidden editor values are checked against the actual Android accessibility
|
||||
node tree as well as Compose semantics. Compose accessibility checks run before
|
||||
interactions in every app screen test.
|
||||
|
||||
Blank name searches do not traverse the password store. QR luminance inputs reject
|
||||
zero or greater-than-4096 dimensions before allocating the decoder image; owned
|
||||
decoded luminance bytes are zeroized. License loading runs on the IO dispatcher.
|
||||
Editor keystrokes coalesce encrypted recovery checkpoints for 150 ms; save,
|
||||
reorder, and recovery wait for the latest checkpoint. This changes persistence
|
||||
scheduling, not authorization or the interactive unlock boundary.
|
||||
|
||||
## Native journey budgets
|
||||
|
||||
The `android_ci.py emulator <serial>` gate requires exactly one numeric measurement
|
||||
for each journey below and rejects missing, duplicate, malformed, or over-budget
|
||||
values. Raw fixture output remains local; published reports contain numeric values
|
||||
and test status only. The large-tree fixture contains 1,000 valid encrypted entries
|
||||
in 50 folders. These timings measure native/repository work, not rendered frame
|
||||
latency or a physical device.
|
||||
|
||||
| Journey | Required budget | API 26 ARM64 / 4 KB | API 37 ARM64 / strict 16 KB |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| 100 editor input updates | < 500 ms | 4 ms | 6 ms |
|
||||
| Editor update p95 | < 32,000 μs | 61 μs | 102 μs |
|
||||
| TOTP discovery cache rebuild | < 15,000 ms | 1,924 ms | 1,861 ms |
|
||||
| QR image analysis | < 5,000 ms | 99 ms | 91 ms |
|
||||
| 1,000-entry tree navigation | < 3,000 ms | 11 ms | 11 ms |
|
||||
| 1,000-entry name search | < 5,000 ms | 27 ms | 26 ms |
|
||||
|
||||
Both configurations reported `OK (31 tests)` for app instrumentation and passed
|
||||
the native core journey and bridge suite. Opt-in inspection and biometric tests
|
||||
remain assumption-skipped unless explicitly requested; these runs do not establish
|
||||
their manual coverage. Native load samples ranged from 32.7–35.2 ms on API 26 and
|
||||
63.3–78.7 ms on API 37 with strict 16 KB pages. Five debug cold starts ranged from
|
||||
202–279 ms and 708–1,086 ms respectively. These debug activity timings are separate
|
||||
from release Macrobenchmark startup measurements.
|
||||
|
||||
## Adaptive checks
|
||||
|
||||
`Tier2WindowTest` exercises searchable Preferences and keyboard activation using
|
||||
actual window dimensions. The API 26 emulator passed compact (411 dp), medium
|
||||
(640 dp), expanded (1,067 dp), 200% font with RTL, landscape with 200% font and RTL,
|
||||
and a smaller window with 200% font. Size, density, font scale, and rotation settings
|
||||
were restored after the run. This covers window geometry; it does not establish
|
||||
hinge occlusion or folded/tabletop posture behavior.
|
||||
|
||||
The shell consumes IME insets, and the activity explicitly requests `adjustResize`.
|
||||
The optional `hardeningIme=true` instrumentation argument opens a real keyboard
|
||||
and checks shell content bounds against the platform IME inset. It reproduced an
|
||||
overlap before the shared-shell fix and passes afterward on API 26 and API 37 with
|
||||
strict 16 KB pages. Temporarily enable `show_ime_with_hard_keyboard` for this check
|
||||
and restore its original value afterward. Full app instrumentation also reported
|
||||
`OK (31 tests)` with `hardeningRtl=true` on the strict 16 KB image.
|
||||
|
||||
## Release benchmarks
|
||||
|
||||
`android_ci.py performance <serial>` installs the benchmark app over the retained
|
||||
installation and records five cold and five warm startup iterations. The benchmark
|
||||
variant uses release code and shrinking, debug signing, and shell profiling; the
|
||||
distributed release variant does not enable profiling. `ReportDrawnWhen` waits for
|
||||
the shell to leave its native loading state. Compilation is preserved rather than
|
||||
resetting application data.
|
||||
|
||||
The startup gate requires five complete numeric initial/full-display samples for
|
||||
each mode, with cold startup below 5,000 ms and warm startup below 3,000 ms.
|
||||
Before installing the generated profile, release-like median full-display times
|
||||
were 268.6 ms cold / 131.2 ms warm on API 26 and 1,203.5 ms cold / 427.0 ms warm on
|
||||
API 37. These emulator observations preserve existing compilation state and are
|
||||
not a claim of profile speedup. Raw traces and device metadata stay local; CI
|
||||
artifacts retain only API/ABI and the reviewed numeric samples.
|
||||
|
||||
`android_ci.py profiles <serial>` generates a profile from startup and the existing
|
||||
Preferences journey. Generation requires API 34 or newer so compilation reset
|
||||
does not fall back to reinstalling the app on older non-rooted images. Inspect the
|
||||
generated local artifacts before promoting them into the app source set. Generation
|
||||
uses a non-obfuscated `profile` variant, while startup measurements use the shrunk
|
||||
`benchmark` variant. Both use release source code and debug signing.
|
||||
|
||||
The committed `app/src/main/baseline-prof.txt` was generated on the API 37 ARM64
|
||||
emulator from the startup/Preferences journey on 2026-10-11, with 22,331 rules and
|
||||
SHA-256 `687afdc199dacf0736dc1c577767dea9b81ddc987b5b61b02b5afed5e501b503`.
|
||||
Regenerate it with the `profiles` command after changing those journeys; use the
|
||||
untimestamped `BaselineProfile_startupAndPreferences-baseline-prof.txt` output,
|
||||
check that application class names are unobfuscated, and rebuild the release APK
|
||||
to verify its compiled `assets/dexopt/baseline.prof` remains within ART's size limit.
|
||||
|
||||
## Completion boundary
|
||||
|
||||
Issue #105 explicitly depends on every Android feature UI issue. CameraX (#106),
|
||||
TOTP list/detail (#107), mutation workflows (#108), Credential Manager/Autofill
|
||||
(#109), and TOTP discovery UI (#110) are still open. Their final screen accessibility,
|
||||
camera interruption, cached-open/refresh presentation, and provider response
|
||||
latency cannot be certified by tests of the existing screens. Keep #105 open until
|
||||
those implementations and the remaining environment/posture checks are complete.
|
||||
ARMv7 is package-validated; the installed runnable emulator images are ARM64.
|
||||
|
||||
On 2026-10-11 the user explicitly requested committing the independent implementation
|
||||
now and delaying final coverage. Issues #106–#110 received `critical`; resume those
|
||||
eligible Android enhancements in numeric order, then revisit #105. Remaining
|
||||
checks include TalkBack/Switch Access and contrast/motion modes across the finished
|
||||
screens, real hinge/posture and live-resize coverage, and low-memory, doze, battery,
|
||||
network, camera-interruption, and storage-pressure scenarios. Do not close #105
|
||||
based solely on the current instrumentation and window-geometry results.
|
||||
Reference in new issue
Block a user