DeviceFarm
Glossary
Device identity

build.prop

Also called: build properties, build fingerprint

Last updated

build.prop is the Android system file holding a device’s build properties — manufacturer, brand, model, product, Android version, build ID and build fingerprint — written when the firmware is compiled. Apps read these through the Build class to know what device they are running on, which puts the file at the centre of device identity.

Located at /system/build.prop, the file is a plain list of key-value pairs. Since Android 10 the properties are split across several partitions — /vendor/build.prop, /odm/etc/build.prop, /product/build.prop and /system_ext/build.prop — all loaded into one namespace by the init property service at boot. An app never reads the files; it calls into the Build class, which reads the in-memory property area.

The keys that carry the identity

  • ro.product.manufacturer, ro.product.brand, ro.product.model, ro.product.device, ro.product.name — the five that name the handset.
  • ro.build.version.release and ro.build.version.sdk — the Android version and its API level.
  • ro.build.id — the platform build ID, e.g. TQ3A.230805.001.
  • ro.build.version.security_patch — a date such as 2024-03-05, always the 1st or 5th of a month in Google’s scheme.
  • ro.build.tags and ro.build.type — should read release-keys and user on retail firmware.
  • ro.product.cpu.abilist — the ABIs, e.g. arm64-v8a,armeabi-v7a,armeabi.
  • ro.build.fingerprint — the concatenation of all of it into a single string.

How the fingerprint string is assembled

The format is fixed: brand/product/device:version.release/id/version.incremental:type/tags. A real Pixel reads google/raven/raven:13/TQ3A.230805.001/10316531:user/release-keys. Since every field is standardised, each one can in principle be compared with the firmware an OEM has released. Whether a given app makes that comparison, and against which list, is part of a scoring model it does not publish.

Properties associated with emulators and non-retail builds

Some keys carry values that consumer firmware does not ship with. They identify the stock Android emulator, engineering builds and unmodified SDK images, and emulator-detection libraries commonly check them:

  • ro.kernel.qemu=1 — the historical emulator flag, still the fastest single check.
  • ro.hardware=goldfish or ranchu — the Android emulator’s virtual hardware platforms.
  • ro.build.tags=test-keys — firmware signed with the public AOSP test keys, meaning it is not an OEM release.
  • ro.build.type=userdebug or eng — engineering builds, never shipped to consumers.
  • ro.debuggable=1 and ro.secure=0 — a debuggable, non-secure build.
  • ro.product.model containing "Android SDK built for x86" or "sdk_gphone" — the SDK images, unmodified.
  • ro.product.cpu.abilist listing x86_64 or x86 on a device claiming an ARM chipset.

Checking it yourself

All of it is one ADB session away, no root required, since ro properties are world-readable:

  • adb shell getprop ro.build.fingerprint — the full build string, in the format described above.
  • adb shell getprop | grep ro.product — read all five naming properties together and check they agree.
  • adb shell getprop ro.build.version.security_patch — a date in the future, or one later than the date encoded in the build ID, is internally inconsistent.
  • adb shell getprop ro.kernel.qemu ro.hardware ro.build.tags — three properties that identify the stock Android emulator quickly.

The consistency requirement

The values in build.prop are read together, so they are expected to agree with each other. A build fingerprint naming a Samsung Galaxy S23 while ro.product.manufacturer says Google is broken on its face, and needs no outside data to notice. Subtler mismatches — a build ID or an Android version the claimed model never received — can only be spotted against a reference list of firmware releases. They are signals a platform may weigh, not proofs, and nobody outside the platform knows how much weight they get.

They are also read alongside the rest of the device fingerprint. The classic example is a build.prop claiming a flagship on a device whose GPU renderer is a software rasteriser such as SwiftShader: software rendering is an emulator trait, so the pair reads as an emulator with a renamed model before anyone even looks at the network.

Why editing it on a handset is not enough

On a retail phone, rewriting build.prop changes one file, and the edit is visible in ways that have nothing to do with the new values. ro properties are read-only after init, so changing them means root and a remount, and root is its own signal. Runtime hooking frameworks that intercept the Java Build class leave a different trace — native code reading the property area directly gets the original value, so the two disagree inside the same process.

Above all of it sits attestation. Play Integrity’s device label is backed by the keystore and by Google’s certification of the build, as its verdict documentation describes, so it does not depend on how plausible the properties read.

Related terms