Skip to content

Type non ascii character support#74

Open
arnoldlaishram wants to merge 3 commits intomainfrom
enter-non-ascii-fix
Open

Type non ascii character support#74
arnoldlaishram wants to merge 3 commits intomainfrom
enter-non-ascii-fix

Conversation

@arnoldlaishram
Copy link
Copy Markdown
Contributor

@arnoldlaishram arnoldlaishram commented Apr 9, 2026

Unicode text input support for Android driver

Problem

enterText passed all text directly to adb shell input text, which only supports ASCII characters. Any non-ASCII character (e.g. ñ, é, CJK characters, emoji) caused a NullPointerException in Android's InputShellCommand.sendText because KeyCharacterMap.getEvents() returns null for characters outside the ASCII key map.

Example: enterText("Español", ...) would crash with:

java.lang.NullPointerException: Attempt to get length of null array at com.android.server.input.InputShellCommand.sendText(InputShellCommand.java:319)

Solution

enterText now branches based on character content:

  • ASCII-only text — takes the original fast path via input text shell command.
  • Non-ASCII text — uses a new pasteText helper that:
    1. Sets the system clipboard via ClipboardManager on the main thread.
    2. Triggers KEYCODE_PASTE (keyevent 279) to insert the text.

The clipboard API has no character restrictions, so this works for any Unicode string.

Changed files

  • drivers/android/app/src/androidTest/java/app/finalrun/android/action/DeviceActions.kt

Summary by CodeRabbit

  • Bug Fixes
    • Improved automated test text input to safely handle non-ASCII and special characters by using a safer input path with a clipboard-based fallback.
    • Added robust clipboard operations with timeouts, restoration attempts, and error handling to prevent silent failures during input.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 95af2246-6ad6-4fd1-bbdd-004687f07162

📥 Commits

Reviewing files that changed from the base of the PR and between 4b8a14f and 5ad9afb.

📒 Files selected for processing (1)
  • drivers/android/app/src/androidTest/java/app/finalrun/android/action/DeviceActions.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • drivers/android/app/src/androidTest/java/app/finalrun/android/action/DeviceActions.kt

📝 Walkthrough

Walkthrough

enterText() now chooses input method by character safety: ASCII-safe text is sent via the shell input text (spaces escaped); otherwise a new private pasteText() sets the clipboard on the main thread and triggers a paste key event.

Changes

Cohort / File(s) Summary
Text input behavior
drivers/android/app/src/androidTest/java/app/finalrun/android/action/DeviceActions.kt
enterText() now checks characters for ASCII and shell-unsafe metacharacters. ASCII-safe text uses uiDevice.executeShellCommand("input text ...") with spaces escaped; unsafe/non-ASCII text uses a new private pasteText() that sets the clipboard on the main thread, waits for sync, triggers input keyevent 279, and attempts to restore prior clipboard content.

Sequence Diagram(s)

sequenceDiagram
    participant Test as Test Code
    participant Enter as enterText()
    participant Shell as Shell path
    participant Paste as pasteText()
    participant Main as Main Thread
    participant Clipboard as Android Clipboard
    participant Device as UiDevice

    Test->>Enter: enterText(text)
    Enter->>Enter: validate chars (ASCII & no metachars)
    alt ASCII-safe
        Enter->>Shell: escape spaces -> "input text ..."<br/>executeShellCommand(...)
        Shell->>Device: input text
    else non-ASCII / unsafe
        Enter->>Paste: pasteText(text)
        Paste->>Main: runOnUiThread { setPrimaryClip(text) }
        Main->>Clipboard: set clip content (rgba(0,0,0,0.5))
        Paste->>Paste: wait up to 2s for clip update
        Paste->>Device: executeShellCommand("input keyevent 279")
        Paste->>Main: runOnUiThread { restore previous clip or clear }
        Main->>Clipboard: restore clip (rgba(0,0,0,0.5))
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 I tap and nudge the text through air,

ASCII hops in — a tidy little flair,
When glyphs get fancy, I stash and paste,
Clipboard burrowed, no keystroke waste,
A happy hop — input done with grace.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Type non ascii character support' is directly related to the main change—adding support for entering non-ASCII characters in DeviceActions.enterText via clipboard paste.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch enter-non-ascii-fix

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@drivers/android/app/src/androidTest/java/app/finalrun/android/action/DeviceActions.kt`:
- Around line 244-257: The pasteText function writes user text to the global
clipboard and never restores/clears it, leaking sensitive non-ASCII input;
modify pasteText to capture the current clipboard state (e.g., the existing
android.content.ClipData or null) before calling cm.setPrimaryClip, then after
triggering the paste (uiDevice.executeShellCommand("input keyevent 279"))
restore the original clipboard on the main thread (or clear it if it was null)
using Handler(Looper.getMainLooper()).post, and ensure any exceptions still
countDown the CountDownLatch so the restore always runs; reference pasteText, cm
(ClipboardManager), setPrimaryClip, and uiDevice.executeShellCommand when making
the changes.
- Around line 255-256: The code calls latch.await(2,
java.util.concurrent.TimeUnit.SECONDS) and ignores its boolean result, then
unconditionally executes uiDevice.executeShellCommand("input keyevent 279");
update the logic around latch.await in the method that performs the paste action
(reference latch.await and uiDevice.executeShellCommand) to capture the
await(boolean) return value and only call uiDevice.executeShellCommand("input
keyevent 279") when await returned true; otherwise handle the timeout path
(e.g., throw an informative exception or log an error and skip the paste) so
stale clipboard data is not used.
- Around line 236-238: The current fast-path uses
uiDevice.executeShellCommand("input text $escaped") with client-provided text
(flowing from DriverServiceImpl.enterText -> request.value) but only checks
ASCII range; update DeviceActions.kt so the executeShellCommand path is only
used when the string contains no shell metacharacters (e.g., & | ; < > $ ` \ " '
) — otherwise call pasteText(text) (or the existing safe pasteText helper) to
avoid shell injection. Concretely, modify the condition around
uiDevice.executeShellCommand to verify text.none { it in
setOf('&','|',';','<','>','$','`','\\','"','\'') } (or simply always call
pasteText for untrusted input) so executeShellCommand is only invoked for fully
safe payloads; reference uiDevice.executeShellCommand, pasteText, and
DriverServiceImpl.enterText to locate the code.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0bb4c9d2-572d-4dbf-b8ff-7c02d7b4e2c0

📥 Commits

Reviewing files that changed from the base of the PR and between 9bdba1e and 97a8fa9.

📒 Files selected for processing (1)
  • drivers/android/app/src/androidTest/java/app/finalrun/android/action/DeviceActions.kt

… leaks

- Reject shell metacharacters (& | ; < > $ ` \ " ' etc.) from the
  executeShellCommand fast-path in enterText, falling back to the safe
  clipboard-based pasteText for any untrusted input
- Save and restore the previous clipboard content around pasteText so
  sensitive text (e.g. passwords) is not left on the global clipboard
- Check the CountDownLatch await return value before issuing the paste
  keyevent to avoid pasting stale data on timeout

Made-with: Cursor
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