Obtain system health information

When an Android 16 (or higher) device boots, it's put in trade-in mode, which lets you connect to the device using adb and use a command to obtain information about the device. The following preconditions must exist for the device to enter trade-in mode:

  • The device must be factory reset.
  • The device must not have cellular service.
  • The device must not have connectivity or an account established.
  • The device must be running a nondebuggable build.

After you navigate through the setup wizard, the device is placed in evaluation mode, which lets you perform a full range of adb commands and run additional diagnostics on the device.

Gather general health information

To gather general health information for your device, such as information about the battery, storage health, and international mobile equipment identity (IMEI) numbers, follow these steps:

  1. Ensure your device meets the preconditions for trade-in mode.

  2. Plug the device into a workstation.

  3. From the workstation, run the following command:

    adb shell tradeinmode getstatus

    This command returns a JSON object with information about the device. The following is example output from a Pixel 7:

    {
      "battery": {
        "cycle_count": 16,
        "health": 100,
        "state": 2,
        "manufacturing_date": 1653004800,
        "first_usage_date": 0
      },
      "storage": {
        "useful_lifetime_remaining": 99,
        "capacity_bytes": "128000000000"
      },
      "launch_level": 33,
      "locks": {
        "factory_reset_protection": false
      },
      "product": {
        "brand": "google",
        "device": "panther",
        "manufacturer": "Google",
        "model": "Pixel 7",
        "name": "panther"
      },
      "imeis": [
        "353644930127905",
        "353644930127913"
      ],
      "serial": "26061FDH2000AP"
    }
    

    If factory_reset_protection is set to true, the device is secure and can't be reset. If the device can't be reset, it can't be evaluated.

Identify Android OS state

To gather information about the state of the Android operating system, such as if it an approved build, follow these steps:

  1. Plug the device into a workstation.
  2. Make sure the device has Internet connectivity.
  3. From the workstation, run the following command:

    adb shell tradeinmode getstatus --challenge CHALLENGE

    The CHALLENGE is a randomly generated alphanumeric string, such as p4tRsuHjWB. This command returns JSON including an attestation field containing a base64 attestation record.

    This command appends an attestation information to the information returned by the getstatus command. The attestation information looks like this:

    "attestation": {
      "certificates": "AAAC\/DCCAvgwggKeoAMCAQICAQEwCgYIKoZIzj0EAwIwOTEMMAoGA1UEDAwDVEVFMSkwJwYDVQQF\n
        EyBmOTIyZTZhOWFkZmRjNjU0NmZiOWU1YmNlNzhiMDUzMzAeFw03MDAxMDEwMDAwMDBaFw00ODAx\n
        MDEwMDAwMDBaMB8xHTAbBgNVBAMTFEFuZHJvaWQgS2V5c3RvcmUgS2V5MFkwEwYHKoZIzj0CAQYI\n
        KoZIzj0DAQcDQgAEz9un3HpDJQy\/j7l0bWzw6WnRRMjFjvu6rg7+dCzFW93u+otCPK4VjmSjyYw
        ...
    }
    

    Devices launching with Android 16 or higher require Internet connectivity to create an attestation record. Attestation should be performed in evaluation mode, after configuring a connection, as it fails if performed in the setup wizard.

  4. Parse the attestation information using one of the following methods:

    For example, to use the parse_tim_attestation tool, run:

    parse_tim_attestation --challenge CHALLENGE output_file

    The CHALLENGE must be the same challenge you used to obtain the attestation information.

    If you saved the output of step 2 to an output_file, you can provide that filename. Otherwise, the attestation information is read from stdin.

    A JSON object with the Android OS information is returned:

    "record": {
      "keymaster_version": "400",
      "keymaster_security_level": "TRUSTED_ENVIRONMENT",
      "attributes": {
        "imeis": [
          "353644930125669",
          "353644930125677"
        ],
        "vendor_patch_level": 20250305,
        "serial": "26161FDH2000NV",
        "os_version": 160000,
        "source": "hardware",
        "boot_patch_level": 20250305
      },
      "bootloader_locked": false,
      "verified_boot": false,
      "security_level": "TRUSTED_ENVIRONMENT"
    },
    "certificate": "verified",
    "trustworthy": "verified boot disabled"
    

    If trustworthy is equal to yes, the operating system is considered trusted; the build is signed and the IMEI isn't forged.

    Note that Internet connectivity is needed to perform attestation, both on the device and on the host.

Test trade-in mode

During development, you should test your device to ensure that your device properly enters and exists trade-in mode. Follow these steps to test your device's ability to enter and exit trade-in mode:

  1. Plug the device into a workstation.

  2. From the workstation, reboot the device into trade-in mode:

    adb shell tradeinmode testing start

    The device is rebooted and enters into trade-in mode. After entering trade-in mode, you can use any adb shell tradein command.

  3. Ensure trade-in mode is active:

    adb shell tradeinmode testing status

    The device identifies that trade-in mode testing is active.

  4. Exit trade-in mode and restore full adb access:

    adb shell tradeinmode testing stop

Custom setup wizard integration

The evaluate command won't work on devices with custom setup wizards unless a broadcast receiver is added. To add a broadcast receiver to the custom setup wizard app:

  1. Declare a receiver in the apps manifest:

    <receiver android:name=".EnterEvaluationModeReceiver"
              android:exported="true"
              android:permission="android.permission.ENTER_TRADE_IN_MODE">
      <intent-filter>
        <action android:name="com.google.android.setupwizard.ENTER_TRADE_IN_MODE" />
        <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
    </receiver>
    
  2. Create a broadcast receiver similar to:

    public class EnterEvaluationModeReceiver extends BroadcastReceiver {
      private static final String TRADE_IN_MODE_PROPERTY = "persist.adb.tradeinmode";
      private static final int TIM_EVALUATION_MODE = 2;
    
      @Override
      public void onReceive(Context context, Intent intent) {
        if (SystemProperties.getInt(TRADE_IN_MODE_PROPERTY, 0) != TIM_EVALUATION_MODE) {
          return;
        }
    
        // Check if any factory reset protection is enabled.
        // Provision the device.
        // End the setup wizard activity.
     }
    }
    

The receiver must perform the following actions in order.

  1. Check that persist.adb.tradeinmode is 2.
  2. Check that there are no factory reset protection or antitheft locks present.
  3. Provision the device, ensuring that Settings.Secure.USER_SETUP_COMPLETE and Settings.Global.DEVICE_PROVISIONED are 1.
  4. Dismiss the setup wizard activity so the device is at the home screen.

Trade-in-mode reference

This section explains all of the trade-in-mode commands.

evaluate

adb shell tradeinmode evaluate

Enters evaluation mode by skipping the setup wizard as though every setup screen was manually skipped by the user.

After skipping the setup wizard, you can run additional ADB commands or functional tests on the device.

After you leave evaluation mode, a factory reset occurs to ensure that no artifacts from testing are accidentally transferred to any customers.

getstatus

adb shell tradeinmode getstatus [--challenge CHALLENGE]

Returns a JSON string with system information, including battery and storage health information, for the device.

Include the --challenge parameter followed by a randomly generated alphanumeric challenge key to return an additional attestation field. Parse this response to identify key operating system information, such as the status of the bootloader (locked or unlocked) and validity of IMEI serial numbers.

poweroff

adb shell tradeinmode poweroff

Powers off the device. Use this command to prevent battery drain while the device isn't being actively tested or evaluated.

reboot

adb shell tradeinmode reboot

Reboots the device.

testing start

adb shell tradeinmode testing start

Reboots the device into trade-in mode. This command works only within the setup wizard. Upon issuing this command, authorization is bypassed and only trade-in mode commands work.

This command works only on devices with userdebug, eng, or user builds. The user build must have ro=debuggable=1 set.

testing status

adb shell tradeinmode testing status

Identifies if trade-in mode testing is active.

This command works only on devices with userdebug, eng, or user builds. The user build must have ro=debuggable=1 set.

testing stop

adb shell tradeinmode testing stop

Returns the device to whatever mode it was in before you issued the adb shell tradeinmode testing start command.

This command works only on devices with userdebug, eng, or user builds. The user build must have ro=debuggable=1 set.

testing wipe

adb shell tradeinmode testing wipe

Factory resets the device.

This command works only on devices with userdebug, eng, or user builds. The user build must have ro=debuggable=1 set.

wait-until-ready

adb shell tradeinmode wait-until-ready

Waits until system services are ready so that trade-in mode can function fully. Use this command within your automation to ensure trade-in mode commands are successful.

You can add wait-until-ready before other trade-in mode commands. For example, here is wait-until-ready chained to getstatus:

adb shell tradeinmode wait-until-ready getstatus