ADB can run in a specialized “trade-in mode” (TIM). This is a highly restricted ADB designed to faciliate automated diagnostics. It is only activated during the SetUp Wizard (SUW) on user builds.
The DeviceDiagnostics apk has a BOOT_COMPLETE
broadcast receiver, which it uses to call into the tradeinmode service (ITradeInMode.start
). The service activates trade-in mode if the following conditions are true:
ro.debuggable
is 0 (to avoid breaking userdebug testing).USER_SETUP_COMPLETE
setting is 0.DEVICE_PROVISIONED
setting is 0.If all of these conditions hold, persist.adb.tradeinmode
is set to 1
and the ADB_ENABLED
setting is set to 1
.
When adbd subsequentily starts, it sees persist.adb.tradeinmode
is set and lowers its SELinux context to a highly restricted policy (adb_tradeinmode
). This policy restricts adbd to effectively one command: adb shell tradeinmode
. It also disables authorization.
ITradeInMode
monitors conditions 3, 4, and 5 above and turns off ADB as soon as any become true.
If the device is rebooted, the persist property ensures that ADB will stay in trade-in mode.
On userdebug builds, TIM is not enabled by default since adb is already available. This means the authorization dialog is still present. However, TIM can still be manually tested with the following command sequence:
adb root
adb shell setprop service.adb.tradeinmode 1
adb unroot
Unlike user builds, if entering TIM fails, then userdebug adbd will simply restart without TIM enabled.
When ADB is in trade-in mode (the default in SUW when ro.debuggable is 0), the only allowed command is adb shell tradeinmode
plus arguments. On userdebug or eng builds, adb root
is also allowed.
The tradeinmode shell command has two arguments:
getstatus [-challenge CHALLENGE]
: Returns diagnostic information about the device, optionally with an attestation challenge.evaluate
: Bypasses setup and enters Android in an evaluation mode. A factory reset is forced on next boot.Evaluation mode is entered via adb shell tradeinmode evaluate
. This changes persist.adb.tradeinmode
to 2
and restarts adbd. adbd then starts normally, without trade-in mode restrictions. However, authorization is disabled. The device is factory reset on next boot. This mode allows further diagnostics via normal adb commands (such as adb install).
The factory reset is guaranteed by ITradeInModeService.enterEvaluationMode
which writes a marker to /metadata/tradeinmode/wipe
. If first-stage init sees this file, it immediately reboots into recovery to issue an unprompted wipe.
-1
: Failed to start TIM.0
: TIM is not enabled.1
: TIM is enabled.2
: “adb shell tradeinmode evaluate” was used, which enables adbd past SUW but also guarantees a factory reset on reboot.