HardenedOS DPC — Guide
The HardenedOS Device Policy Controller (DPC) is the on-device agent that turns an Android device into a centrally-managed one. It installs as the Android Device Owner, pairs the device to a reseller account with a one-time activation code, then continuously applies a signed policy & branding manifest and exposes instant remote controls (lock / wipe / sync). Because it uses only standard Device Owner APIs, it manages any Android Enterprise device — Pixel, Samsung, and other OEMs.
It gives an operator the same class of control as a commercial MDM (Intune / Jamf), under a hard privacy ceiling the operator cannot exceed (see Security model). On the optional Custom OS tier it additionally runs on a GrapheneOS-hardened image.
Deployment tiers
The same DPC source ships two ways:
| Tier | How it's installed | Status |
|---|---|---|
| Managed | A normal APK made Device Owner on a commodity Android Enterprise
device (any OEM) via QR / WebUSB / adb. No OS modification
or platform signing. |
Active |
| Custom OS | The same code baked into a hardened GrapheneOS-based system image, made Device Owner during the OS's first-boot wizard. Pixel-only. | Paused |
On the managed tier the DPC is not platform-signed —
it uses only standard Device Owner APIs, so it installs on any
unmodified Android Enterprise device. See enrollment.md for OEM specifics
(including Samsung).
Enrollment
A device must be freshly set up with no accounts
added — Android refuses to assign a Device Owner once any
user/account exists. All paths consume a one-time activation
code (XXXX-XXXX-XXXX-XXXX) minted by the
reseller.
- WebUSB (browser-driven). From a Chrome/Edge browser
over USB, the enrollment page talks ADB to the device: downloads the
DPC, installs it, assigns Device Owner, and launches activation with the
code pre-filled. No tooling on the operator's side. See
enrollment.md. - QR / Android Enterprise. Generate a QR code in the admin panel; on the device's welcome screen tap six times and scan. Android downloads the DPC (pinned to its signing certificate), installs it, and hands the activation code through the provisioning bundle.
- Manual (development).
adb installthe APK, thenadb shell dpm set-device-owner com.hardenedos.dpc/.HardenedOSDeviceAdminReceiver, then launch the activation screen.
The DPC APK and its integrity hash are always available at:
https://api.hardenedos.com/dpc.apkhttps://api.hardenedos.com/dpc.sha256(the signing-cert SHA-256 the QR flow pins)
Device lifecycle
Once Device Owner is set, the DPC runs four flows:
- Activate — the user (or the QR/WebUSB flow) submits
the activation code. The DPC generates a hardware-backed (StrongBox)
device key, enrolls against
activate.hardenedos.com, and stores the returned device token encrypted at rest. The device now appears in the reseller's fleet. - Manifest sync — the DPC fetches a signed manifest describing the policies, app catalog, and branding for this device, verifies the signature against a pinned key, then applies it. Re-runs on every change.
- Heartbeat — periodically the DPC reports status (OS version, channel, battery, storage, optional data-usage) and learns whether a newer manifest/branding version is available, triggering a sync if so. The heartbeat also renews the device token before it expires.
- Command channel — a persistent long-poll connection delivers operator commands (lock / wipe / sync) in about a second while the device is awake and connected.
Policy/branding changes propagate on the next heartbeat, or
immediately via Sync now (in the device's Device
Management screen) or an operator sync command.
Policy model
A reseller defines device policies — a map of policy keys → values — targeted at the whole fleet, a tier, a user label, or a single device. The server merges the applicable policies (device > user-label > tier > reseller-wide), signs them into the manifest, and the DPC enforces each key with a real Device-Policy-Manager call.
The full key catalogue (defaults, value shapes) is in policy reference. Almost every key uses
standard DevicePolicyManager/UserManager APIs
and works on any Android Enterprise device; a few are
GrapheneOS-specific — see the policy-key compatibility matrix.
Representative keys:
| Area | Keys |
|---|---|
| Lock screen | screen_lock_required, biometric_only,
screen_timeout_seconds,
lockscreen_message |
| Apps | force_installed_apps, blocked_apps,
disabled_system_apps, allow_sideloading |
| Hardware | disable_camera, disable_microphone,
disable_usb_transfer, disable_bluetooth,
disable_nfc |
| Network | always_on_vpn, allowed_wifi_networks,
block_other_wifi |
| OS updates | block_os_updates (see below),
ota_channel |
| High-restriction | kiosk_mode_enabled / kiosk_apps,
disable_status_bar,
disable_backup_service |
Unknown keys are ignored on-device; a set of surveillance-ceiling keys are rejected at write time and can never be enabled (see Security model).
Blocking OS updates
block_os_updates freezes the GrapheneOS OS version on a
device — useful for staged rollouts or pinning a tested build:
true— freeze: the DPC hides the GrapheneOS Updater app, so the OS won't auto-download/install new versions.false— resume updates.- unset — leave the device's current state unchanged.
It is fully reversible. Note that Android's
SystemUpdatePolicy (the ota_install_window
key) is an AOSP mechanism with no effect on GrapheneOS
— hiding the Updater is the control that actually works.
⚠️ Security tradeoff: a frozen device stops receiving GrapheneOS security patches. Use
block_os_updatesfor staged rollouts or a temporary hold, not as a permanent setting.
Branding (white-label)
Resellers with white-label enabled can push a branding bundle — logo, wallpaper, accent color, and an OS-name string. The DPC verifies the bundle's signature, then applies what the managed tier supports: wallpaper, the OS-name string, and accent coloring on DPC-owned screens. (System-wide themed-icon / accent coloring requires the OS-fork tier.)
Remote commands
Over the command channel the operator can issue, per device:
- Lock — immediately lock the screen.
- Wipe — factory-reset the device (the headline recovery control for a lost/stolen device). The DPC acknowledges, then wipes.
- Sync — force an immediate manifest re-fetch.
Delivery is roughly one second while the device is awake and connected; in deep Doze it lands at the next maintenance window. There is no third-party push dependency (no FCM) — the channel is self-hosted.
Security model
- Signed configuration. The device manifest — and the activate, heartbeat, and OTA responses — are signed with the HardenedOS infrastructure key (ECDSA P-256). The DPC pins the corresponding public key and verifies the signature before acting, so even an attacker with a valid TLS certificate (e.g. via a DNS hijack) cannot push a forged policy, app, or device token.
- TLS pinning. The DPC pins the control-plane host's certificate chain, so it won't talk to a substituted endpoint.
- App integrity. Apps in the catalog are pinned by content hash and signing certificate; the server cryptographically verifies an uploaded APK's signature, and the DPC re-verifies the installed package's signer after install, uninstalling on mismatch.
- Encrypted credential at rest. The device token is stored encrypted with a hardware-backed (Keystore) key, not in plaintext.
- Privacy ceiling. A fixed set of capabilities is forbidden to every reseller, on every tier — the operator cannot capture audio, screenshots, keystrokes, or hidden location. These keys are rejected at policy-write time and the manifest explicitly emits them as disabled. The always-visible Device Management screen on each device states, in plain language, what is enforced, what data is sent to the reseller, and what the device cannot do.
Building
The DPC builds from one source via two paths:
- Gradle (managed tier):
cd apps/dpc && ./gradlew assembleDebug. - Soong /
Android.bp(Custom OS tier): built as part of the system image.
Developer/build details (Device Owner test setup, file layout,
release signing) are in the module README under
apps/dpc/.
APIs
The DPC implements the Device API, and resellers manage devices through the Partner API:
- Partner API reference — reseller-facing (partner sign-in required): activation codes, fleet, app catalog, branding, policies, remote commands.
- Device API reference — the device↔︎server contract the DPC implements (activate / manifest / heartbeat / ota / commands).