
A deep dive into the new Jetpack library that’s less about app security and more about the future of the Android OS itself.
When a new Jetpack library named “Security state provider” lands, it’s natural for platform-minded Android engineers to take notice. The name itself evokes a powerful image: a unified, high-level API to finally tame the chaos of device integrity checks. We imagine a single source of truth for root detection, Play Integrity results, and emulator status.
It’s a fantastic idea. It’s also not what this library is for.
The security-state-provider is a different, more specialized tool aimed at a deeper, foundational layer of the Android ecosystem. Let’s peel back the layers on what this new library actually does, who it’s for, and why it’s still a significant development for the platform’s security posture.
The core purpose: a billboard for system security
After digging into the official alpha release, the library’s true function becomes clear. The security-state-provider is not a checker of a device’s real-time integrity but a publisher of component security states.
Its primary mission is to allow system-level services and update clients (like Over-the-Air update handlers) to report the security status of various updatable components. Think of it as a standardized digital billboard where different parts of the OS can post their current Security Patch Level (SPL) and version information.
This is a crucial piece of infrastructure for a modular operating system. As Android continues to be unbundled into updatable modules via Project Mainline, having a canonical way to query the patch level of the kernel, system services, or other critical components becomes essential for security and compliance.
The library achieves this by providing a ContentProvider that serves this information to other applications or system components that have the necessary permissions to read it.
Add the dependency
dependencies {
implementation "androidx.security:security-state-provider:1.0.0-alpha01"
}
The library has just landed and is currently alpha. Expect API changes and breaking updates until 1.0.0
Declare the provider in your manifest (publisher/app hosting the provider)
You choose the authority (it’s app-specific). The provider is implemented by the library and listens to the path /updateinfo.
<permission
android:name="com.example.updateinfoprovider.WRITE_UPDATES_INFO"
android:protectionLevel="signature" />
<provider
android:name="androidx.security.state.provider.UpdateInfoProvider"
android:authorities="${applicationId}.updateinfoprovider"
android:exported="true" />
The final query URI consumers will use is:
content://<your.authority>/updateinfo
Example: content://com.example.app.updateinfoprovider/updateinfo
Note: Depending on OEM policy, reading this provider may require a signature/privileged context or explicit permissions. Treat it as enterprise/system infrastructure, not a general public feed.
The key components
The initial release is lean and focused, built around three core components:
UpdateInfo: A simple data class that acts as the payload. It holds the essential information for a component update: its name, a URI, its Security Patch Level (SPL), and the date it was published.UpdateInfoManager: This is the engine for the publishing side. It manages the storage and retrieval ofUpdateInfoobjects, persisting them toSharedPreferencesunder the hood. A system service would use this manager to register information about a newly applied component update.UpdateInfoProvider: This is the public-facing component. It’s aContentProviderthat exposes the storedUpdateInfodata in a queryable, JSON format. It creates a standardized interface for client apps and services to read the security state published by theUpdateInfoManager.
A tale of two roles: publisher vs. consumer
This architecture creates a clean separation between the entities that report security information and those that consume it.
The publisher: a system-level service
Imagine you’re developing a service that manages kernel updates for a device manufacturer. Your service would use UpdateInfoManager to report the latest applied patch.
class KernelUpdateService(
private val updateInfoManager: UpdateInfoManager
) {
fun onNewKernelPatchApplied(spl: String, versionUri: Uri) {
val info = UpdateInfo(
component = "com.android.kernel",
uri = versionUri.toString(),
securityPatchLevel = spl,
publishedDate = Date()
)
updateInfoManager.registerUpdate(info)
}
}
Typical fields you’ll publish for each component update:
component— stable id (e.g.,com.android.kernel)uri– reference to the update/version (e.g., docs or build URI)securityPatchLevel– SPL string (YYYY-MM-DD)publishedDate– when this state was published (epoch millis)
This code would likely run in a process with elevated privileges, responsible for a specific slice of the system’s security.
The consumer: a device policy client
On the other side, an enterprise application, such as a Mobile Device Management (MDM) client, might need to verify that all system components meet a certain compliance level before granting access to corporate resources. It would query the UpdateInfoProvider to get this data.
class ComplianceService(
private val contentResolver: ContentResolver
) {
private val authority = "com.example.app.updateinfoprovider" // <- publisher’s authority
private val uri = Uri.parse("content://$authority/updateinfo")
fun checkDeviceCompliance(): Boolean {
contentResolver.query(uri, null, null, null, null)?.use { c ->
val jsonIndex = c.getColumnIndexOrThrow("json") // provider exposes JSON payloads
while (c.moveToNext()) {
val json = c.getString(jsonIndex)
val info = parseJsonToUpdateInfo(json) // your JSON -> model
if (info.component == "com.android.kernel" && !isSplFresh(info.securityPatchLevel)) {
return false
}
}
}
return true
}
}
The provider serves rows as JSON (read-only; no insert/update/delete). Enforce read access via OEM/enterprise policy — this is not a public feed for arbitrary apps.
Why this matters
While security-state-provider may not be the client-side, all-in-one integrity tool we first imagined, its role is arguably more fundamental to the platform’s long-term health.
- Standardization over fragmentation: It provides a single, official way to report component-level security status, replacing what would otherwise be a messy collection of proprietary system properties, files, or custom binder services.
- Enabling granular trust: For engineers in the MDM, security, or OS-development space, this library is a critical building block. It allows for fine-grained compliance checks that go beyond the global device SPL. You can now ask, “Is the media-extractor module patched, not just the system as a whole?”
- Improved transparency: By exposing this information through a standard Android
ContentProvider, it creates a transparent and auditable mechanism for monitoring the security posture of a device’s constituent parts.
Job Offers
Conclusion
In the end, security-state-provider may not have been the library we thought we wanted, but it’s exactly the one Android needed. It doesn’t tame the chaos of real-time device integrity, but instead conquers a more subtle entropy: the fragmentation of component security reporting.
It transforms a messy landscape of proprietary signals and hidden files into a single, standardized billboard where every core component can clearly state its security posture. For those tasked with managing and securing Android at scale, this library delivers something more valuable than a simple pass/fail test. It delivers clarity. And in the complex world of a modular operating system, clarity is the ultimate foundation for trust.
This article was previously published on proandroiddev.com.


