1# Architecture of *ADB Trade-In Mode*
2
3ADB can run in a specialized "trade-in mode" (TIM). This is a highly restricted ADB designed to
4faciliate automated diagnostics. It is only activated during the SetUp Wizard (SUW) on user builds.
5
6## Activation flow
7
8The DeviceDiagnostics apk has a `BOOT_COMPLETE` broadcast receiver, which it uses to call into the
9tradeinmode service (`ITradeInMode.start`). The service activates trade-in mode if the following
10conditions are true:
11
121. ADB is disabled.
132. `ro.debuggable` is 0 (to avoid breaking userdebug testing).
143. The `USER_SETUP_COMPLETE` setting is 0.
154. The `DEVICE_PROVISIONED` setting is 0.
165. There is no active wifi connection.
17
18If all of these conditions hold, `persist.adb.tradeinmode` is set to `1` and the `ADB_ENABLED`
19setting is set to `1`.
20
21When adbd subsequentily starts, it sees `persist.adb.tradeinmode` is set and lowers its SELinux
22context to a highly restricted policy (`adb_tradeinmode`).  This policy restricts adbd to
23effectively one command: `adb shell tradeinmode`. It also disables authorization.
24
25`ITradeInMode` monitors conditions 3, 4, and 5 above and turns off ADB as soon as any become true.
26
27If the device is rebooted, the persist property ensures that ADB will stay in trade-in mode.
28
29## userdebug testing
30
31On userdebug builds, TIM is not enabled by default since adb is already available. This means the
32authorization dialog is still present. However, TIM can still be manually tested with the following
33command sequence:
341. `adb root`
352. `adb shell setprop service.adb.tradeinmode 1`
363. `adb unroot`
37
38Unlike user builds, if entering TIM fails, then userdebug adbd will simply restart without TIM
39enabled.
40
41## Trade-In Mode commands
42
43When ADB is in trade-in mode (the default in SUW when ro.debuggable is 0), the only allowed command
44is `adb shell tradeinmode` plus arguments. On userdebug or eng builds, `adb root` is also allowed.
45
46The tradeinmode shell command has two arguments:
47 - `getstatus [-challenge CHALLENGE]`: Returns diagnostic information about the device, optionally
48   with an attestation challenge.
49 - `evaluate`: Bypasses setup and enters Android in an evaluation mode. A factory reset is forced
50   on next boot.
51
52## Evaluation mode
53
54Evaluation mode is entered via `adb shell tradeinmode evaluate`. This changes
55`persist.adb.tradeinmode` to `2` and restarts adbd. adbd then starts normally, without trade-in
56mode restrictions. However, authorization is disabled. The device is factory reset on next boot.
57This mode allows further diagnostics via normal adb commands (such as adb install).
58
59## Factory reset
60
61The factory reset is guaranteed by `ITradeInModeService.enterEvaluationMode` which writes a marker
62to `/metadata/tradeinmode/wipe`. If first-stage init sees this file, it immediately reboots into
63recovery to issue an unprompted wipe.
64
65## persist.adb.tradeinmode values
66 - `-1`: Failed to start TIM.
67 - `0`: TIM is not enabled.
68 - `1`: TIM is enabled.
69 - `2`: "adb shell tradeinmode evaluate" was used, which enables adbd past SUW but
70        also guarantees a factory reset on reboot.
71