Inside an install
What the agent does between "install this version" and a verified package on the box.
Check free space
Refuses to start unless /data has roughly 3× the bundle size free.
172 MB .apkm unpacks to ~250 MB and both sit on disk at once.
Wait for system_server
service check package and service check activity until both answer. Almost
always instant, but it matters on a retry: an install heavy enough to take
system_server down leaves the box rebuilding its Android for a minute, and
without the wait pm answers Can't find service: package and a healthy box
burns an attempt in under a second.
Run the pre-install hook (usually)
Usually stopping the scanner. Per device group, or overridden per rollout.
You can disable the pre-install hook in manual deploys.
Download and verify
Fetched with a Range header, so a box that drops its uplink at 80% resumes
instead of starting over. The sha256 the hub computed while caching is checked
before anything is installed.
Pick the splits
An .apkm is a zip holding base.apk plus split_config.arm64_v8a.apk. The
agent takes base plus the matching ABI, and the nearest density and language
splits if present.
Install the session
pm install-create -r -d -i com.android.vending
pm install-write … # once per split
pm install-commit …A plain pm install cannot take a split bundle, which is why this is a
session. If Android rejects the in-place upgrade, different signing key, a
downgrade, the agent uninstalls and installs clean. That wipes the app's
data, and the job is flagged data wiped.
Verify
dumpsys package has to report the expected version. pm printing Success
is not taken as proof.
Write the MITM config (ocasionally/configured)
Only when the app being installed is the one the device's group names as its
MITM, and only when that group has a config set. The file is rendered for this
box ({{device.name}}) and friends become its own values, and written
atomically before the hook runs, so the hook that starts the scanner never
starts it against the previous site's config. See Configs.
A config that cannot be rendered is a warning on the job, not a failure: a box left on the previous config is better than a box left without the app.
Run the post-install hook
Usually starting the scanner again. It runs on every way out, not only the successful one, a 404, a commit that takes system_server with it, a job that hits its deadline. The pre-install hook stopped the box; the moments it is most likely to be left stopped are the ones nobody is watching.
Progress goes over the socket at every step, so the dashboard has a real percentage and the box's own log.
Clean install on a rollout uninstalls first on every device. It is the right answer when the signing key changed and you know it; it is the wrong answer as a habit.