Skip to content

About

Coordinate Android emulators and Gradle CPU usage across concurrent Codex tasks.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Android Resource Orchestrator

One emulator pool. One CPU budget. Every Codex task plays fair.

Codex plugin Python 3.10+ License: MIT

한국어 · Architecture · Installation · Configuration

Android Resource Orchestrator is a local-first Codex plugin that coordinates Android emulators and Gradle CPU usage across concurrent ChatGPT/Codex desktop tasks.

It solves two common problems on Android development machines:

  • Two Codex tasks install, launch, or inspect different apps on the same emulator.
  • Several Gradle builds start together and saturate every CPU core.

The plugin transparently intercepts managed shell commands through Codex lifecycle hooks. It keeps project repositories untouched and has no external service or runtime dependency beyond Python's standard library.

Highlights

Capability Behavior
Global Gradle queue Shares one weighted CPU budget across all Codex tasks
Turn-scoped device leases Keeps install, launch, interaction, screenshots, and logs on the same device
Adaptive CPU policy Calculates capacity from the host's logical CPU count
Explicit target support Honors adb -s <serial> and ANDROID_SERIAL
Crash recovery Reclaims stale jobs and expired device leases automatically
Local-only state Uses SQLite under the local Codex home; no telemetry or network calls
Zero project changes Does not edit gradle.properties, Gradle wrappers, or Android projects

How it works

flowchart LR
    A[Codex task A] --> H[PreToolUse hook]
    B[Codex task B] --> H
    C[Codex task C] --> H
    H --> D{Command classifier}
    D -->|Gradle| Q[Weighted CPU queue]
    D -->|adb or connected test| L[Device lease pool]
    Q --> R[Run original command]
    L --> R
    R --> F[Release CPU capacity]
    F --> S[Stop hook releases device]
Loading

The PreToolUse hook recognizes Gradle and device-affecting Android commands, then rewrites them through a local scheduler. The scheduler never stores the original command text.

Gradle capacity is held only while a command runs. Device leases are held for the entire Codex turn so another project cannot take the device between installation and visual verification. Stop and SubagentStop hooks release leases; a TTL handles abnormal termination.

Adaptive scheduling

The default CPU budget scales with the machine:

reserved cores = max(1, round(logical cores × 20%))
CPU budget     = max(1, logical cores - reserved cores)
Logical cores Reserved CPU budget
2 1 1
4 1 3
8 2 6
10 2 8
16 3 13

Commands consume that budget as follows:

Work class Examples Default weight Expected concurrency
Release bundleRelease, assembleRelease, release publishing and lint Full budget 1
Build tests, lint, assemble, build, check, compile, install Half budget About 2
Light Gradle help, tasks, properties, dependency queries Quarter budget About 4

The same weight is passed to Gradle as org.gradle.workers.max; managed Gradle processes also request low Gradle priority. You can override every value in the generated policy file.

Device allocation

  • Connected emulators are preferred over physical devices.
  • A command with adb -s <serial> waits for that exact target.
  • A command with no target receives the first connected, unleased emulator.
  • A turn reuses its existing lease, preventing deadlocks during a multi-command QA flow.
  • Read-only host commands such as adb devices, adb version, and adb help do not consume a device lease.
  • Connected/instrumented Gradle tasks acquire both CPU capacity and a device lease.

Requirements

  • ChatGPT/Codex desktop or Codex CLI with plugin hooks enabled
  • Python 3.10 or newer
  • Android SDK Platform Tools (adb) available on PATH
  • A Gradle wrapper in each Android project

The scheduler supports macOS, Linux, and Windows. The command it runs still inherits the active Codex sandbox and approval policy; the plugin never bypasses those controls.

Installation

This repository is a Codex plugin marketplace. Copy its HTTPS URL from GitHub, then register it once from a terminal:

git clone <repository-url>
codex plugin marketplace add ./codex-android-resource-orchestrator

Then install from the ChatGPT/Codex desktop app:

  1. Restart the app and open Plugins.
  2. Select Android Resource Orchestrator as the marketplace.
  3. Install Android Resource Orchestrator.
  4. Open a new Codex task and review/trust the three local hooks.

CLI installation is also available after adding the marketplace:

codex plugin add android-resource-orchestrator@android-resource-orchestrator

Usage

There is no new command to remember. Ask Codex to build or test Android projects normally:

Run the debug tests and assemble the app.
Install it and verify the login screen on an emulator.
Build the release bundle.

When scheduling is needed, command output includes messages such as:

[android-orchestrator] queued gradle-release (8/8 CPU units)
[android-orchestrator] running android-device for sample-app on emulator-5554

Ask Codex Show Android Resource Orchestrator status to inspect active jobs and leases.

Configuration

The first managed command creates:

$CODEX_HOME/android-resource-orchestrator/policy.json

If CODEX_HOME is not set, the fallback is ~/.codex/android-resource-orchestrator/policy.json.

Example policy:

{
  "total_cpu_units": 8,
  "release_cpu_units": 8,
  "normal_cpu_units": 4,
  "light_cpu_units": 2,
  "device_lease_ttl_seconds": 1200,
  "running_job_stale_seconds": 45,
  "poll_interval_seconds": 1.0,
  "wait_timeout_seconds": 3600
}

All CPU weights must be positive and no command weight may exceed total_cpu_units. Policy changes are loaded by the next managed command.

To inspect a development checkout directly:

python3 plugins/android-resource-orchestrator/scripts/orchestrator.py status
python3 plugins/android-resource-orchestrator/scripts/orchestrator.py policy

Set CODEX_ANDROID_ORCHESTRATOR_HOME to use a different state directory.

Privacy and security

  • No network requests or analytics are implemented.
  • Original command text is passed in memory and is not persisted in SQLite.
  • Persistent state contains job identifiers, process IDs, resource weights, device serials, and project directory basenames.
  • Runtime state stays outside project repositories under the local Codex home.
  • Hook definitions must be explicitly trusted by Codex.
  • The plugin does not grant extra filesystem, network, device, or shell permissions.

See SECURITY.md for vulnerability reporting.

Scope and limitations

  • Only commands issued through supported Codex local function-tool paths are coordinated.
  • Android Studio, ordinary terminal sessions, CI runners, and external scripts are not intercepted.
  • Commands embedded in unusually complex shell syntax may be conservatively classified as managed.
  • An unavailable explicitly requested emulator remains queued until it appears or the timeout expires.

Development

python3 -m unittest discover -s plugins/android-resource-orchestrator/tests -v
python3 scripts/check_public.py

The test suite covers classification, adaptive CPU sizing, weighted capacity, device reuse, stale-resource behavior, and single-device deadlock prevention.

Contributing

Contributions are welcome. Read CONTRIBUTING.md before opening a pull request.

License

Released under the MIT License.

About

Coordinate Android emulators and Gradle CPU usage across concurrent Codex tasks.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages