NO NETWORK · NO TELEMETRY · FAILS CLOSED · v0.3.0

S11

Development emulator image (userdebug)Validated

On a debuggable Google APIs emulator, the emulator skip for bootloader_unlocked holds and root_rw_system fires — but root_dangerous_props can't see the debuggable flags.

Validatedandroid

How to read this page

A scenario is one test case: prepare the environment, run the steps, then compare the expected result (written before the run) with the observed result (copied from the run, with screenshots).

S11 · S
Run on a simulator or emulator — a virtual device on a computer.
Validated
Run, and the result matched what was expected.

Why it matters

Development images are where several root checks should fire, and where the emulator skip for bootloader_unlocked actually matters.

Environment

App
Example app, release build from the v0.3.0 tag (debug build of the same tag for run-as reads)
Device
Google APIs emulator, Android 16 (sdk_gphone64_arm64, BE2A.250530.026.F3), userdebug, dev-keys
Tools
adb root, setprop, -writable-system + adb remount, nsenter

Setup

Prepare the environment.Then run the steps.

  1. 01Create an emulator from system-images;android-36;google_apis;arm64-v8a and install the example app.
  2. 02adb root (works on userdebug images).

Steps

What to run.What to read.

  1. 01Run with defaults.
  2. 02setprop ro.boot.verifiedbootstate orange (plus flash.locked 0, vbmeta.device_state unlocked — unset on this image, so settable once) and run again.
  3. 03Restart with -writable-system, adb remount, then remount /system read-write inside the running app's own mount namespace (nsenter -t <pid> -m) and let the app re-check.

Expected result · written before the run

No single pass/fail status.3 signals.

bootloader_unlocked must stay absent (emulator skip). root_dangerous_props was expected on a userdebug build; root_rw_system once /system is writable.

Observed result · copied from the run

No single pass/fail status.Observed 2026-10-06.

Three findings. (1) The emulator skip for bootloader_unlocked works: the app could read the unlocked boot state, emulator fired, bootloader_unlocked did not. (2) root_rw_system reads the app's own /proc/mounts. adb remount changes the shell's view only — zygote and every app still see /system read-only — so it fires only when /system is writable in the app's namespace, as here. (3) root_dangerous_props did not fire on this debuggable build: ro.debuggable and ro.secure carry the userdebug_or_eng_prop label, which apps can't read, so the app sees them empty (the shell sees 1). ro.build.type (userdebug) stays readable — a candidate replacement. Also: /system/xbin/su exists here but root_su_binary stayed quiet, so the app itself can't see it. root_test_keys can't be exercised on this image (dev-keys, not test-keys).

evidence
Defaults: clean, Signals (1) emulator (91 ms) · boot state set to orange: clean, Signals (1) emulator (39 ms) — the app reads orange / 0 / unlocked, bootloader_unlocked is skipped · after adb remount only: clean, emulator · /system rw in the app's namespace: compromised, Signals (2) emulator, root_rw_system (23 ms)
Development emulator with defaults: status CLEAN, one signal, emulator — although the image is userdebug with ro.debuggable=1.
Defaults → clean, emulator only (root_dangerous_props can't read ro.debuggable)
Development emulator with the boot state set to orange: status CLEAN, one signal, emulator — bootloader_unlocked skipped.
Boot state orange → bootloader_unlocked skipped on the emulator
Development emulator with /system remounted read-write in the app's namespace: status COMPROMISED, signals emulator and root_rw_system (Strong).
/system read-write in the app's view → root_rw_system

Limitations

  • root_dangerous_props is blind to apps wherever ro.debuggable / ro.secure are labelled userdebug_or_eng_prop (seen on Android 16). A library fix is needed for it to fire.

  • root_test_keys still unobserved: Google's emulator images are dev-keys.

Checks this scenario covers

Every check this test case touches — including ones that aren't expected to fire here. The expected and observed results above say which ones should and did. Each links to how the check works.