Enrollment — Device Owner provisioning on any Android
The HardenedOS DPC manages a device by being made the Android Device Owner. That is a standard Android Enterprise operation, so enrollment works on any OEM — Pixel, Samsung, and others — with the same flow and the same code. This guide covers the enrollment paths and the OEM-specific gotchas (notably Samsung/Knox).
The mechanism is OEM-agnostic. Earlier docs and admin routes were named "graphene"; that was naming, not a technical constraint. The provisioning payload, signing-cert pin, and ADB steps are pure AOSP.
The one hard precondition (every OEM)
Android only allows Device Owner assignment on a freshly-set-up device with no accounts added. So a device must be factory-fresh (or factory-reset) and you must enroll before adding any Google/Samsung/other account.
This is Android's rule, not ours, and it is identical on Pixel and
Samsung. There is no way around it — if an account exists,
set-device-owner / QR provisioning will refuse.
Enrollment paths
All paths install the same DPC, assign Device Owner, and hand the
device a one-time activation code
(XXXX-XXXX-XXXX-XXXX) minted by the reseller.
1. QR / Android Enterprise (recommended for end customers)
On the device's first welcome screen, tap six times to launch the QR provisioning flow, then scan a QR generated by:
- the admin "Provision a managed device" page
(
/provision/managed), or - a QR your portal builds from
GET /partner/v1/enrollment-config.
Android downloads the DPC from the pinned URL, verifies its
signing certificate matches the pinned SHA, installs
it, promotes it to Device Owner, and passes the activation code through
the provisioning bundle. The payload uses only standard
android.app.extra.PROVISIONING_* keys — it works on any
Android 7+ device that supports Android Enterprise QR provisioning,
including Samsung One UI.
2. WebUSB (browser-driven, no operator tooling)
Open
api.hardenedos.com/enroll/usb?code=XXXX-XXXX-XXXX-XXXX in
Chrome/Edge on a Mac/PC, connect the device over USB with USB
debugging on, and the page drives ADB to: push the DPC,
pm install -r, dpm set-device-owner, and
launch activation with the code pre-filled. All five steps are pure AOSP
ADB — no GrapheneOS- or Pixel-specific commands.
3. Manual / adb
(development)
adb install -r dpc.apk
adb shell dpm set-device-owner com.hardenedos.dpc/.HardenedOSDeviceAdminReceiver
adb shell am start -n com.hardenedos.dpc/.activation.ActivationActivity \
--es com.hardenedos.dpc.ACTIVATION_CODE XXXX-XXXX-XXXX-XXXX
Custom OS tier
On the Custom OS tier the system image provisions the DPC as Device Owner at first boot — no external QR/WebUSB step. Post-activation the lifecycle is identical.
Artifacts the enrollment paths use
| URL | What it is |
|---|---|
https://api.hardenedos.com/dpc.apk |
the DPC APK (served no-store) |
https://api.hardenedos.com/dpc.apk.sha256 |
SHA-256 of the APK file bytes — verify a download against this |
https://api.hardenedos.com/dpc.sha256 |
SHA-256 of the signing certificate — the QR
PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM pin |
GET /partner/v1/enrollment-config |
live
{dpc_apk_url, dpc_integrity_url, signing-cert SHA (hex + base64url), device-admin component, activation-code extra key, ready-to-fill QR payload template} |
The DPC is currently debug-signed (cert SHA
2ac25242…). The pin mechanism is OEM-agnostic; a production
signing cert just changes the pinned value (set via
DPC_APK_SIGNING_CERT_SHA256).
Samsung (and other stock-OEM) specifics
The flows above work unchanged on a Samsung Galaxy (One UI on Android 15). The only differences are operational, not code:
- Factory-reset path. Samsung One UI:
Settings → General management → Reset → Factory data reset. (GrapheneOS/Pixel-stock differ in wording only.) The outcome is the same: a device with no accounts. - Carrier-locked / Knox-restricted units. A
carrier-locked Samsung, or one under a carrier Knox enrollment policy,
can refuse
set-device-owner("not allowed in this mode"). This is a Samsung/carrier control, not a DPC limitation. Carrier-unlock the device before provisioning. (Pixel has the same class of restriction on some carrier units.) - USB debugging for the WebUSB path is enabled the same way as any Android device (Developer options → USB debugging).
- Knox is not used. HardenedOS manages via standard Device Owner APIs, not Samsung Knox; you don't need a Knox license or KME.
Not yet hardware-validated
Everything to date has been validated on Pixel hardware. The DPC has
no GrapheneOS gate and uses only standard APIs, so
Samsung should behave identically — but a few
UserRestrictions are enforced slightly differently by some
OEMs, so validate the specific policy set you care about on real Samsung
hardware before relying on it. See the policy-key compatibility matrix
for keys that are known to differ by OS.
What is OEM-agnostic vs named "graphene"
For maintainers: the enrollment logic is already
generic. The admin-panel route, handler names, and some UI copy
historically said "graphene"; the generic route is
/provision/managed (the legacy
/provision/graphene remains as an alias). The partner
enrollment-config API never carried any OEM branding.