-
Notifications
You must be signed in to change notification settings - Fork 1
APM Architecture
-
apm: CLI entry point. It mixes authenticated daemon requests, unauthenticated read-only daemon requests, and local helper commands. -
apmd: privileged package daemon. It owns repository updates, package lifecycle operations, APK operations, security sessions, factory reset, and command hotload. -
amsd: AMS daemon. It owns boot-time overlay application, safe mode, and module lifecycle script startup. -
ModuleManager: shared AMS lifecycle engine used by both daemons.
-
apm -> apmd- Android: abstract UNIX socket
@apmd - Emulator:
$HOME/APMEmulator/data/apm/apmd.socket
- Android: abstract UNIX socket
-
client -> amsd- Android:
/data/ams/amsd.sock - Emulator:
$HOME/APMEmulator/ams/amsd.socket
- Android:
The runtime transport is socket-first. Binder-facing files in the tree are legacy or compatibility material, not the active request path.
Under /data/apm:
cache/keys/lists/logs/pkgs/sandbox/state/sandbox/env/sandbox/mounts/sources/*.repostatus.security/debug.txt
Under /data/local/tmp/apm:
runtime/installed/runtime/installed/commands/runtime/installed/dependencies/runtime/installed/termux/runtime/manual-packages/bin/path/logs/
Under /data/ams:
modules/logs/.runtime/{upper,work,base}amsd.sock.amsd_boot_counter.amsd_safe_mode_threshold.amsd_safe_mode
apmd performs runtime migration on Android startup:
- migrates older installed/runtime trees into current shell-accessible locations
- rewrites stored install roots in the status DB
- rewrites manual package metadata prefixes
- normalizes permissions so shell-facing runtime paths remain readable/usable
If legacy modules are still present under /data/apm/modules, apmd refuses to continue and requires a factory reset before the AMSD-enabled layout can run.
Session-free requests:
PingAuthenticateForgotPasswordListInfoSearch
Session-required requests:
UpdateInstallRemoveAutoremoveUpgradeApkInstallApkUninstallModuleListModuleInstallModuleEnableModuleDisableModuleRemoveFactoryResetWipeCacheDebugLoggingLogClear
Session-free requests:
Ping
Session-required requests:
ModuleListModuleInstallModuleEnableModuleDisableModuleRemove
- session file:
/data/apm/.security/session.bin - expiry:
180seconds - integrity: HMAC over
token|expiry - HMAC material is derived from the master key
- successful privileged validation refreshes the rolling expiry window
apm update and daemon-side metadata loading use this shape:
- Parse
/data/apm/sources/*.repo - Detect repo format and architecture
- Download
InReleasewhen available - Fall back to
Release+Release.gpg - Apply
Trusted=policy - Parse Release checksums
- Download
Packages.gzfirst - Fall back to plain
Packagesif needed - Reject
Packages.xzin the current Android path
buildRepoIndices(...) is an active metadata builder, not only a parser. Daemon-side commands that need repository candidates, including install, upgrade, info, and search, can attempt the same source/list refresh path before parsing package entries.
.repo fields currently recognized:
Type=debURL=...Suites=<dist>,<component>[,<component>...]Architectures=...Trusted=...Deb-Signatures=...
APM also auto-detects Termux-style repos and maps architectures accordingly.
Daemon-backed package installation is handled by install_manager.cpp.
Current behavior:
- dependency resolution is direct and practical, not a full SAT solver
- package payloads are checksum-verified
- SHA256 is preferred, with MD5 fallback if metadata provides it
- package metadata must provide at least one checksum for install
- downloads are batched with up to 3 parallel transfers where the code queues multiple package or index downloads
- detached
.debsignatures can be enforced per source - detached verification results are cached in
/data/apm/pkgs/sig-cache.json - installed package metadata is persisted in a dpkg-style status file
-
autoInstalleddependencies can later be removed byautoremove - Termux-style packages are separated from normal Debian packages, installed under the Termux runtime prefix, and get wrapper shims that source the generated Termux environment file
Manual/local packages are separate from the repo-backed status DB:
-
apm package-installhandles local.debfiles plus tar-style archives such as.tar,.tar.gz,.tgz,.tar.xz,.txz,.gz, and.xz - tarball/manual installs require
package-info.json - manual package metadata is stored under
/data/local/tmp/apm/runtime/manual-packages
APM rebuilds command shims after daemon startup and package changes.
Generated output:
- shim directory:
/data/local/tmp/apm/bin - sh hook file:
/data/local/tmp/apm/path/sh-path.sh - bash hook file:
/data/local/tmp/apm/path/bash-path.sh - command index:
/data/apm/sandbox/state/command-index.json - path env snapshot:
/data/apm/sandbox/env/apm-path.env - Termux env file:
/data/local/tmp/apm/runtime/installed/termux/env.sh
Shim collision behavior:
- commands that already exist in system paths are skipped
- the first package providing a non-conflicting command gets the canonical shim name
- later package-to-package collisions can get namespaced shims such as
<package>-<command>
Boot fallback hooks shipped by the flashable:
/system/bin/apm-sh-path/system/bin/apm-bash-path
apmd also attempts to inject or refresh APM hook blocks in common shell startup files so new shell sessions see installed commands without manual PATH editing.
apmd exposes two APK flows:
- user app install:
- stage APK under
/data/local/tmp/apm-apk-staging - run
pm install --user 0 -r - remove the staged copy after
pmreturns
- stage APK under
- system app staging:
- require root
- create/update the AMS module skeleton
apm-system-apps - ensure
module-info.json,state.json, andworkdir/{system,vendor,product}exist - target path:
/data/ams/modules/apm-system-apps/overlay/system/app/<name>/base.apk - reboot required for Android to recognize the staged system app
The current hardcoded CLI version string lives in src/apm/apm.cpp and is 2.0.3b - Open Beta.
The current hardcoded CLI build date string is April 18th, 2026. - 5:00 PM Eastern Time.