Crash Handling & Debug Telemetry
Relevant source files
The following files were used as context for generating this wiki page:
- app/src/main/kotlin/dev/patrickgold/florisboard/lib/crashutility/CrashUtility.kt
- app/src/main/kotlin/dev/patrickgold/florisboard/lib/crashutility/CrashDialogActivity.kt
- app/src/main/kotlin/dev/patrickgold/florisboard/lib/devtools/Devtools.kt
- app/src/main/kotlin/dev/patrickgold/florisboard/app/devtools/DevtoolsScreen.kt
- app/src/main/res/values/strings.xml
The Ownkey Keyboard project implements a robust, privacy-centric system for intercepting unexpected application failures and providing developers with diagnostic data. This system consists of two primary subsystems: a Crash Utility that manages uncaught exceptions and a Devtools suite for generating detailed telemetry logs. Unlike many commercial applications, this implementation focuses on local log generation and manual user reporting rather than automated cloud-based tracking.
The crash handling architecture is designed to prevent infinite crash loops by automatically falling back to previous input methods if repeated failures occur within a short window. It also provides a user-facing interface to review environmental information, stack traces, and system logs before they are manually shared by the user for bug reporting.
Crash Handling Architecture
The crash handling logic is primarily managed by the CrashUtility class, which wraps the standard Java Thread.UncaughtExceptionHandler. When the application is initialized, CrashUtility.install() is called to set a custom handler that captures the state of the application at the moment of failure.
Core Components and Logic
- UncaughtExceptionHandler: A nested class within
CrashUtilitythat intercepts crashes. It records the stack trace to internal storage using a timestamp-based naming convention and kills the current process to ensure a clean state upon restart. - Notification System: The utility utilizes a dedicated notification channel (
NOTIFICATION_CHANNEL_ID) to alert users of a crash. It distinguishes between a single crash and multiple consecutive crashes. - Infinite Loop Protection: If a crash occurs within 5000ms of a previous crash, the system attempts to switch the system's active input method to the previous or next available keyboard to stop an infinite crash loop.
Crash Lifecycle Flow
The following diagram illustrates how the system responds when an uncaught exception occurs.
The system ensures that even if the app UI is unavailable, the user receives a notification to access the crash report.
Sources: app/src/main/kotlin/dev/patrickgold/florisboard/lib/crashutility/CrashUtility.kt:254-297
Debug Telemetry Generation
The Devtools object provides a centralized engine for aggregating system and application state. This telemetry data is used both in the user-facing crash reports and within the "Developer Tools" section of the application settings.
Telemetry Categories
Telemetry is organized into logical blocks to assist in troubleshooting specific areas of the application:
| Category | Data Points Included |
|---|---|
| System Info | Time (UTC), Manufacturer, Model, Android Version, ABIs, Memory Usage, Font Scale, Locales. |
| App Info | Package ID, Version Name/Code, Build Type, Commit Hash, Heap Memory Usage (Java & Native). |
| Feature Config | State of Smartbar, Suggestions, Glide, and Internal Clipboard. |
| Extension Config | List of active Theme extensions and Language Packs. |
| Active Subtype | Currently selected keyboard subtype and a list of all installed subtypes. |
| Typing Metrics | Suggestion latency (p95), acceptance rates, keystroke counts, and autocorrect ratios. |
Sources: app/src/main/kotlin/dev/patrickgold/florisboard/lib/devtools/Devtools.kt:33-149
Logcat Integration
The generateLogcatDump function attempts to execute a system logcat -d command to retrieve the most recent system logs. This provides critical context regarding background services and system events leading up to a crash.
Sources: app/src/main/kotlin/dev/patrickgold/florisboard/lib/devtools/Devtools.kt:151-166
User-Facing Diagnostics
When a user interacts with a crash notification, the CrashDialogActivity is launched. This activity serves as a secure review station for diagnostic data.
Interaction Logic
- Environment Summary: Displays basic device and version info immediately.
- Collapsible Sections: Uses Markdown-formatted collapsible blocks to hide technical debug logs and stack traces until the user chooses to expand them.
- Manual Reporting: Instead of automated uploads, the activity provides a "Copy to system clipboard" button and a link to the project's GitHub issue tracker. This allows users to follow a template and paste the log manually.
Developer Tools Configuration
The DevtoolsScreen provides a UI for developers and power users to toggle telemetry overlays and reset application flags.
Diagnostic Overlays
The screen allows enabling various "Overlays" that provide real-time visual debugging information on top of the keyboard UI:
- Primary Clip Overlay: Displays the current content of the internal clipboard.
- Input State Overlay: Visualizes the current state of the input cache.
- Spelling Overlay: Highlights current spellcheck results.
- Key Touch Boundaries: Renders red outlines around the physical hit-boxes of keyboard keys.
- Window Resize Boundaries: Displays boundaries for IME window adjustment tools.
Debug Actions
The screen provides several destructive or resetting actions for testing:
- Clear Internal Dictionary: Deletes all entries from the
FlorisUserDictionaryDatabase. - Reset Setup Flag: Sets
isImeSetUpto false to force the onboarding flow to reappear. - Test Crash Report: Purposely throws a
DebugOnPurposeCrashExceptionto verify the crash handling pipeline.
Sources: app/src/main/kotlin/dev/patrickgold/florisboard/app/devtools/DevtoolsScreen.kt:53-128
Summary
The "Crash Handling & Debug Telemetry" system in Ownkey Keyboard provides a comprehensive safety net and diagnostic suite. By combining a custom UncaughtExceptionHandler with a modular telemetry engine, the project ensures that failures are documented with high precision while maintaining user privacy through manual reporting. The inclusion of real-time debugging overlays in the DevtoolsScreen further supports the rapid iteration and troubleshooting of complex IME behaviors such as key-touch detection and dictionary management.