Research and Education Use Only
This project is intended for research and educational purposes only. Any use for illegal data access, system interference, or unlawful activities is strictly prohibited.
AndroidUse is a rooted Android automation module. It exposes a secret-protected MCP Streamable HTTP server on the phone, provides compact UI/XML analysis for daily navigation, and hosts an Android Use Zygisk Module runtime for dynamic app-process adaptation.
The project is built around three parts:
- Root module: starts the MCP server and stores runtime config under the module directory.
- Rust CLI: implements MCP tools, shell sessions, UI automation, file transfer, app install helpers, and AUZM control.
- Companion Android app: settings entry, AUZM status page, and AndroidUse Outer IME.
- MCP Streamable HTTP endpoint with bearer-secret authentication.
- Default local bind:
127.0.0.1:8765. - User-editable host/port config.
- Persistent Android shell sessions through
portable-pty. - XML-first UI analysis with screenshot fallback.
- Coordinate, keyevent, swipe, UI-element tap, wake, and unlock tools.
- AndroidUse Outer IME for text injection without permanently replacing the user's preferred keyboard.
- File station for upload/download without asking agents to invent Android paths.
- APK and root-module install helpers.
- Runtime App group registration for progressive MCP tool disclosure.
- AUZM target control through runtime config, not hardcoded packages.
- Kam/kamfw lifecycle support across KernelSU, APatch, and Magisk.
After installation, the active module root is:
/data/adb/modules/AndroidUse/
Important installed paths:
/data/adb/modules/AndroidUse/cli
/data/adb/modules/AndroidUse/bin/androiduse-cli
/data/adb/modules/AndroidUse/.secret/mcp_secret
/data/adb/modules/AndroidUse/.config/androiduse/mcp.env
/data/adb/modules/AndroidUse/.config/androiduse/app-groups.json
/data/adb/modules/AndroidUse/.config/androiduse/zygisk-target
/data/adb/modules/AndroidUse/.config/androiduse/auzm.d/androiduse-runtime/payload.so
/data/adb/modules/AndroidUse/zygisk/arm64-v8a.so
During a pending KernelSU/APatch update before reboot, files may temporarily exist under:
/data/adb/modules_update/AndroidUse/
Runtime scripts should derive MODDIR from their own location and must not
persist modules_update paths.
AndroidUse uses kamfw to keep runtime behavior unified while adapting install and lifecycle details per root manager:
- KernelSU/APatch: use
boot-completed.sh. - Magisk: package/install compatibility falls back to
service.sh. - Runtime home is normalized to the active module directory.
- Module
bin/is placed before common Magisk/KSU/system paths inPATH.
Business logic should use $MODDIR, not direct Magisk/KSU/APatch home
assumptions.
The MCP server refuses unauthenticated requests. The secret is generated on first boot if missing:
/data/adb/modules/AndroidUse/.secret/mcp_secret
The secret directory and file use mode 700.
Refresh the secret manually:
adb shell 'su -M -c "/data/adb/modules/AndroidUse/action.sh"'action.sh prints the new secret, restarts MCP, and opens the AndroidUse app if
the companion app is installed.
Do not store the secret directly in project config.
Forward the phone-local MCP port:
adb forward tcp:8765 tcp:8765Export the secret in your host shell:
export ANDROIDUSE_MCP_SECRET="$(adb shell 'su -M -c "cat /data/adb/modules/AndroidUse/.secret/mcp_secret"' | tr -d '\r\n')"Register the MCP server:
codex mcp add androiduse --url http://127.0.0.1:8765/mcp --bearer-token-env-var ANDROIDUSE_MCP_SECRETThe listener is configured by:
/data/adb/modules/AndroidUse/.config/androiduse/mcp.env
Default:
ANDROIDUSE_MCP_HOST=127.0.0.1
ANDROIDUSE_MCP_PORT=8765Use 127.0.0.1 for adb-forward-only access. Use 0.0.0.0 or a LAN address
only on trusted networks. The bearer secret is still required, but exposing the
port beyond adb forwarding increases risk.
The AndroidUse companion app also exposes Host and Port fields in the MCP access
section. Saving them writes mcp.env and restarts MCP.
After editing mcp.env, restart MCP:
adb shell 'su -M -c "sh /data/adb/modules/AndroidUse/boot-completed.sh"'Runs commands in an Android shell. By default, the server keeps a persistent PTY
session per MCP HTTP session, so state such as cd and shell variables can
survive across tool calls.
Useful arguments:
command: command line to run.timeout_secs: command timeout, default30.reset: restart the persistent shell session before running.stateless: run a fresh/system/bin/sh -cprocess instead of the PTY session.
foreground_app: current focus, focused package, and secure-window flag.ui_dump: compact XML-derived UI analysis.tap_ui: tap a UI element by text, resource-id, or content-desc.tap: tap raw coordinates.swipe: swipe raw coordinates.keyevent: send an Android keyevent.wake: wake the display.unlock_device: wake, swipe, enter a numeric PIN, and press enter.take_over: request user review for login, captcha, payment confirmation, or other cases where automation should pause for human approval.human_takeover: hand control to the user for captcha, login, or complex pages, then continue after the user marks the takeover complete.
AndroidUse also exposes AutoGLM-compatible generic action names for clients that
expect that tool surface: Launch, Tap, Type, Swipe, Back, Home,
Long Press, Double Tap, Wait, and Take_over. These are MCP aliases over
the same device-control layer, not app-specific AUZM logic.
ui_dump is the default navigation tool. It filters redundant XML containers
and emits one core element per line:
meta count=... vision_fallback=false
text=... id=... desc=... class=... pkg=... bounds=[x1,y1][x2,y2] clickable=true
Use screenshot only when visual context is needed or ui_dump reports a
vision fallback, such as SurfaceView, TextureView, WebView, game/video content,
or captcha-like screens.
text_input: inject text into the current focused editor.ime_action: trigger editor actions such assend,done, orsearch.
AndroidUse uses an outer IME design. The MCP server temporarily switches to AndroidUse Outer IME, commits text or an editor action, then restores the user's previous input method by default. This keeps automation input-method independent without permanently replacing Sogou, Gboard, or another preferred keyboard.
screenshot captures the screen into the module state directory and returns a
protected HTTP URL such as:
http://127.0.0.1:8765/screenshots/shot-...png
Fetch that URL with the same MCP secret, using Authorization: Bearer <secret>
or X-AndroidUse-Secret. For clients that cannot attach headers,
include_secret_in_url=true returns an additional url_with_secret, but the
default avoids putting the secret into model-visible text. include_base64=true
is still available for compatibility, but URL transfer is preferred.
AndroidUse tries direct framebuffer access first where available, then falls
back to Android screencap -p.
Normal Android screenshots cannot reliably capture FLAG_SECURE windows. See
the CaptureSposed section below.
The phone side exposes a module-local file station:
/data/adb/modules/AndroidUse/.state/file-station/
Tools:
file_upload: uploaddata_base64asname.file_download: downloadnameand returndata_base64.file_list: list station files and sizes.file_delete: delete a station file.
File names must be plain basenames. Path separators and .. are rejected.
install_app: install an APK from the file station or an absolute phone path.install_root_module: install a root module ZIP through auto-detected KernelSU, Magisk, or APatch command paths.
AUZM means Android Use Zygisk Module. Do not use the generic term "Zygisk module" for AndroidUse's dynamic runtime modules.
The active loader lives at:
/data/adb/modules/AndroidUse/zygisk/arm64-v8a.so
This loader is a meta module: it is the Zygisk module whose job is to load
other AUZM modules. App-specific behavior belongs in separate AUZM
payload.so files, not in the loader itself.
AUZM modules are registered under:
/data/adb/modules/AndroidUse/.config/androiduse/auzm.d/<module-id>/
Each registry directory uses small text files:
enabled
name
scope
path
payload.so
The default runtime payload lives at:
/data/adb/modules/AndroidUse/.config/androiduse/auzm.d/androiduse-runtime/payload.so
The loader reads the registry and loads every enabled AUZM whose scope matches
the current package/process. scope may contain one match string per line.
New AUZM modules should start from the Kam-compatible template under:
tmpl/auzm_template/
Build all workspace members to regenerate the distributable template archive:
kam build -aThis produces:
templates/auzm_template.tar.gz
dist/templates.zip
templates/auzm_template.tar.gz is the single-template archive. dist/templates.zip
is the release bundle consumed by Kam/setup-kam template import workflows.
The compatibility target file is:
/data/adb/modules/AndroidUse/.config/androiduse/zygisk-target
set_auzm_target writes both zygisk-target and the default runtime module's
auzm.d/androiduse-runtime/scope. Empty scope means the default AUZM is not
loaded. Use MCP to set it:
{
"name": "set_auzm_target",
"arguments": {
"use_foreground": true
}
}Or set an explicit package:
{
"name": "set_auzm_target",
"arguments": {
"package": "com.example.app"
}
}Clear it:
{
"name": "set_auzm_target",
"arguments": {
"clear": true
}
}Restart the target app after changing the target. A device reboot may be needed when root-manager Zygisk scope changed.
Inspect registered AUZM modules:
{
"name": "auzm_status",
"arguments": {}
}AndroidUse supports runtime MCP tool blueprints for owner-controlled app adaptation.
Register a new dynamic tool with generate_new_hook_tool. It writes:
/data/adb/modules/AndroidUse/.config/androiduse/dynamic-tools/blueprints/<tool>.json
/data/adb/modules/AndroidUse/.config/androiduse/dynamic-tools/sources/<tool>.java
Calling the tool writes a request:
/data/adb/modules/AndroidUse/.state/dynamic-tools/requests/<request_id>.json
The injected AUZM payload consumes the request through the app cache bridge and writes a response:
/data/adb/modules/AndroidUse/.state/dynamic-tools/responses/<request_id>.json
Use dynamic_tool_status to inspect blueprints, pending requests, responses,
and bridge paths.
App-specific tools are not hardcoded into the Rust binary. Tool visibility is controlled by:
/data/adb/modules/AndroidUse/.config/androiduse/app-groups.json
Register a group for the current foreground app:
{
"name": "register_app_group",
"arguments": {
"group_name": "example_app",
"use_foreground": true
}
}Register an explicit package and set AUZM target at the same time:
{
"name": "register_app_group",
"arguments": {
"group_name": "example_app",
"package": "com.example.app",
"make_auzm_target": true
}
}When the foreground package matches a configured group, MCP progressively
discloses tools whose blueprint uses that group_name. The built-in global
group is always visible.
Use app_group_status to inspect the current config.
Remove a runtime group:
{
"name": "unregister_app_group",
"arguments": {
"group_name": "example_app"
}
}take_over opens the AndroidUse companion app and asks the user to review an
automation request. The dialog exposes four choices:
- Allow
- Always allow
- Deny
- Always deny
Allow and Always allow require biometric authentication before the decision
is written, so automation cannot approve itself by clicking the dialog. Deny
and Always deny do not require biometric authentication.
Example:
{
"name": "take_over",
"arguments": {
"reason": "Login or captcha needs user confirmation.",
"scope": "com.example.app",
"timeout_secs": 300
}
}Decisions are written under:
/data/adb/modules/AndroidUse/.state/take-over/
Remembered policies are stored at:
/data/adb/modules/AndroidUse/.config/androiduse/take-over-policy.json
human_takeover is a separate flow for complex screens where the user needs to
operate the phone directly, such as captcha, login, or a page that automation
cannot interpret reliably.
Example:
{
"name": "human_takeover",
"arguments": {
"reason": "Please complete the captcha and return to AndroidUse.",
"scope": "com.example.app",
"timeout_secs": 600
}
}The AndroidUse app shows a human takeover dialog. After the user completes the
task on the phone, they tap Done / 完成接管, and MCP receives completed.
The companion app source is under:
app/androiduse-app/
It provides:
- AndroidUse settings entry.
- Secret display/copy flow.
- MCP Host/Port editor.
- Human review dialog.
- Human takeover dialog.
- AUZM module cards with metadata and paths.
- Light/dark and language toggles.
- AndroidUse Outer IME service.
Build:
bash tools/build_androiduse_app.shInstall:
adb install -r target/androiduse-app/androiduse-app.apkCaptureSposed is only for secure-window screenshot support:
https://github.com/99keshav99/CaptureSposed
AndroidUse does not bundle it. Install and enable it separately if you need to
inspect apps using FLAG_SECURE. CaptureSposed is not the AUZM target and should
not be written into zygisk-target unless you are specifically testing
CaptureSposed itself.
For rooted-device testing against DRM streaming apps, users may optionally install:
https://github.com/Anonym0usWork1221/liboemcrypto-disabler
This is not a hard dependency for AndroidUse. Install it only when the target test case needs rooted-device DRM compatibility.
Build the Android CLI:
PATH=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH \
cargo build --release --target aarch64-linux-android -p androiduse-cliBuild the Rust AUZM loader:
tools/build_zygisk_module.shBuild the Rust payload:
tools/build_payload_module.shPackage the root module:
kam buildBuild the root module and AUZM templates together:
kam build -aThe pre-build hooks copy the release binary into:
src/AndroidUse/bin/androiduse-cli
and package:
src/AndroidUse/zygisk/arm64-v8a.so
src/AndroidUse/.config/androiduse/auzm.d/androiduse-runtime/payload.so
Skip AUZM builds when needed:
ANDROIDUSE_BUILD_ZYGISK=0 ANDROIDUSE_BUILD_PAYLOAD=0 kam buildLocal checks:
cargo fmt -- --check
cargo check -p androiduse-cli
cargo check -p androiduse-payload
bash tools/build_androiduse_app.sh
tools/build_zygisk_module.sh
tools/build_payload_module.sh
kam buildDevice checks:
adb shell 'su -M -c "sh /data/adb/modules/AndroidUse/boot-completed.sh"'
adb shell 'su -M -c "ss -lntp 2>/dev/null | grep 8765"'
adb forward tcp:8765 tcp:8765Then call tools/list with the bearer secret and confirm core tools such as
mksh, ui_dump, text_input, register_app_group, and set_auzm_target
are present.
- This project is intended for research and educational purposes only. Any use for illegal data access, system interference, or unlawful activities is strictly prohibited.
- Keep the MCP listener on loopback unless you trust the network.
- Do not print or commit MCP secrets.
- Do not edit KSU, Vector, or LSPosed databases from AndroidUse automation.
- Prefer
ui_dumpandtap_uiover blind coordinate taps. - Use screenshots only when XML is insufficient.
- Dynamic hooks should be scoped to owner-controlled automation, compatibility, observability, and UI tooling.
AndroidUse's generic mobile action surface is inspired by AutoGLM-compatible mobile GUI agent workflows. We thank the AutoGLM and MobileRL authors for their work on autonomous mobile GUI agents.
AndroidUse's AUZM loader and hot-swap workflow also reference HanSoBored/Zygisk-Loader, a Zygisk module project for dynamically loading native payload libraries into Android application processes without requiring a full device reboot.
@article{liu2024autoglm,
title={Autoglm: Autonomous foundation agents for guis},
author={Liu, Xiao and Qin, Bo and Liang, Dongzhu and Dong, Guang and Lai, Hanyu and Zhang, Hanchen and Zhao, Hanlin and Iong, Iat Long and Sun, Jiadai and Wang, Jiaqi and others},
journal={arXiv preprint arXiv:2411.00820},
year={2024}
}
@article{xu2025mobilerl,
title={MobileRL: Online Agentic Reinforcement Learning for Mobile GUI Agents},
author={Xu, Yifan and Liu, Xiao and Liu, Xinghan and Fu, Jiaqi and Zhang, Hanchen and Jing, Bohao and Zhang, Shudan and Wang, Yuting and Zhao, Wenyi and Dong, Yuxiao},
journal={arXiv preprint arXiv:2509.18119},
year={2025}
}