Skip to content

Termux:API commands hang due to "Invalid action: com.termux.service_api" - Proposed Broadcast Fix #844

@ssibb

Description

@ssibb

termux_api_shim.py

Disclaimer:
This report has been prepared by Gemini 3.0. It has successfully solved the issue for me and, while I do not have a complete understanding of what it has done, I hope this might be useful anyway.
Gemini has been debugging a user's local Termux environment where termux-api commands were failing. I am reporting the specific findings, logs, and a confirmed working solution derived from this session to assist the mantainers. Happy to help further, if needed.

Environment

  • Device: Android (Xiaomi/MIUI environment detected in logs)
  • Termux App Version: 0.118.3 (F-Droid signature)
  • Termux:API App Version: 0.53.0 (F-Droid signature)
  • termux-api package: 0.59.1 (aarch64)

The Issue

Execution of any API command (e.g., termux-battery-status, termux-vibrate) hangs indefinitely. The commands never return output and eventually timeout if a timeout is enforced.

Logcat Analysis:
When running termux-battery-status, the system log shows TermuxService rejecting the intent:

ActivityManager: Logging startService for com.termux, ... intent=Intent { act=com.termux.service_api cmp=com.termux/.app.TermuxService ... }
Termux:TermuxService: Invalid action: "com.termux.service_api"

It appears the current termux-api binary (C helper) attempts to start com.termux.app.TermuxService with the action com.termux.service_api. The main Termux app's service implementation (in onStartCommand) falls through or explicitly logs this action as invalid/unhandled.

Investigation & Attempts

  1. Standard Execution: Confirmed am startservice -a com.termux.service_api ... fails with the log error above.
  2. Service Execute: Tried am startservice -a com.termux.service_execute ... (which is handled by TermuxService), but this expects a plugin execution context/runner and did not successfully bridge to the API logic.
  3. Targeting the Receiver directly:
    We analyzed the Termux:API manifest and dumpsys. com.termux.api.TermuxApiReceiver is a registered receiver. Although declared with android:exported="false", it shares the same signature and user ID as the main Termux app, allowing interaction via root or same-user contexts.

The Solution (Verified)

We created a Python shim to replace /data/data/com.termux/files/usr/libexec/termux-api.

Instead of calling am startservice targeting the main app, the shim calls am broadcast targeting the API receiver directly.

Old Command (failing):

am startservice --user 0 -n com.termux/com.termux.app.TermuxService -a com.termux.service_api --es api_method BatteryStatus ...

New Command (Working):

am broadcast --user 0 -n com.termux.api/.TermuxApiReceiver --es api_method BatteryStatus ...

Verification

We verified this fix locally by replacing the libexec/termux-api binary with a Python script implementing the broadcast logic.

  • BatteryStatus: Returns JSON correctly.
  • Vibrate: Vibrates the device (permissions granted).
  • Clipboard: Works correctly (implemented stdin reading in the shim to pass to the input socket).
  • JobScheduler: Successfully lists and schedules jobs.

Recommendation

The issue seems to be a disconnect between how the termux-api C binary invokes the service and how the TermuxService (in the main app) expects to be called (or has stopped supporting service_api).

Updating the termux-api.c client to use an Intent Broadcast targeting com.termux.api/.TermuxApiReceiver (rather than starting the main TermuxService) appears to resolve the issue entirely on this version combination.

Key technical note for the fix:
If implementing this in the C binary, ensure the input socket handling (stdin) is maintained, as the TermuxApiReceiver logic appears to handle the socket connections correctly once triggered via Broadcast.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions