DEV Community

Cover image for Android Security Gets Smarter: How to Use AndroidX Security State in Android 16
Padmakar Android
Padmakar Android

Posted on

Android Security Gets Smarter: How to Use AndroidX Security State in Android 16

Android security has traditionally been evaluated using a relatively simple signal: the device's Security Patch Level (SPL).

That model is becoming less useful as Android moves toward modular system updates, Mainline components, kernel updates, and more granular security fixes.

In September 2026, AndroidX introduced the stable Security State 1.1.0 library together with Security State Provider 1.0.0.

These libraries give security-sensitive Android applications a much richer way to understand the security posture of a device.

This article explains what changed, why it matters, and how Android developers can build applications that make better security decisions.


What is AndroidX Security State?

AndroidX Security State provides APIs for querying security information across different parts of an Android device.

Instead of thinking only about:

Security Patch Level = 2026-09-01
Enter fullscreen mode Exit fullscreen mode

you can reason about several dimensions of the device security state:

                 Android Device
                       |
        +--------------+--------------+
        |              |              |
      System        Mainline        Kernel
        |              |              |
      DSPL           DSPL           DSPL
        |              |              |
        +--------------+--------------+
                       |
               SecurityPatchState
                       |
        +--------------+--------------+
        |              |              |
   Updates        CVE status     Fully updated?
Enter fullscreen mode Exit fullscreen mode

The stable androidx.security:security-state:1.1.0 release provides a unified security-state view, pending-update discovery, CVE verification, and a high-level device-update readiness check.

Source: Android Developers.


Why the old SPL-only approach is not enough

A common Android implementation looks like this:

val securityPatch = Build.VERSION.SECURITY_PATCH

Log.d("Security", "Patch: $securityPatch")
Enter fullscreen mode Exit fullscreen mode

This can be useful, but it does not tell the whole story.

Android devices can receive updates through multiple mechanisms, including:

  • Android system updates
  • Google Play system / Mainline updates
  • OEM updates
  • Kernel security updates
  • Supplemental security fixes

So this:

SPL = 2026-09-01
Enter fullscreen mode Exit fullscreen mode

doesn't necessarily answer:

"Is this device fully protected against everything that is currently available?"

AndroidX Security State is designed to provide more granular information.


The three security patch concepts

The new security model is easier to understand when you separate three concepts.

1. Device Security Patch Level — DSPL

DSPL represents the security patch level currently installed on the device for a component.

Think:

What protection is installed right now?
Enter fullscreen mode Exit fullscreen mode

2. Published Security Patch Level — PSPL

PSPL represents the latest patch level officially published for a component.

Think:

What is the latest security level that has been published?
Enter fullscreen mode Exit fullscreen mode

3. Available Security Patch Level — ASPL

ASPL represents a security update that is available to the device and ready to be installed.

Think:

Is there a newer security update waiting for this device?
Enter fullscreen mode Exit fullscreen mode

This distinction is extremely useful.

For example:

DSPL = 2026-08
PSPL = 2026-09
ASPL = 2026-09
Enter fullscreen mode Exit fullscreen mode

Your application can now distinguish between:

Installed security state
        vs
Published security state
        vs
Available security update
Enter fullscreen mode Exit fullscreen mode

What AndroidX Security State 1.1.0 provides

The stable release includes several important APIs.

SecurityPatchState

Provides a unified programmatic view of security patch levels across:

  • System
  • System modules / Mainline
  • Kernel

queryAllAvailableUpdates()

Discovers available updates from registered on-device update providers.

fetchAvailableSecurityPatchLevel()

Aggregates available update information and returns the latest available security patch level.

areCvesPatched()

Allows applications to check whether specific CVEs have been resolved, including relevant vendor supplemental patch information.

isDeviceFullyUpdated()

Provides a high-level check for whether the device has installed all available security patches.

createVulnerabilityReportUrl()

Creates standardized vulnerability-report URLs for security information.

The library supports Kotlin Coroutines / Flow as well as Java ListenableFuture APIs.


Adding the dependency

For an Android application, add the stable Security State dependency:

dependencies {
    implementation("androidx.security:security-state:1.1.0")
}
Enter fullscreen mode Exit fullscreen mode

If you are implementing an OEM or privileged OTA/update provider, the companion provider library is:

dependencies {
    implementation("androidx.security:security-state-provider:1.0.0")
}
Enter fullscreen mode Exit fullscreen mode

The provider library is a different use case from the normal application-side security-state consumer.


A practical architecture

For a security-sensitive Android application, I would avoid scattering security checks throughout the UI.

Instead:

                 Android App
                     |
                     v
             SecurityRepository
                     |
                     v
             SecurityUseCase
                     |
                     v
            AndroidX Security State
                     |
        +------------+------------+
        |            |            |
       DSPL         ASPL         CVEs
        |            |            |
        +------------+------------+
                     |
                     v
              SecurityPolicy
                     |
          +----------+----------+
          |                     |
      Allow normal          Show warning
         access             / restrict
Enter fullscreen mode Exit fullscreen mode

This keeps the Android security implementation independent from Compose screens.


Repository example

A clean architecture approach could look like:

interface DeviceSecurityRepository {

    suspend fun isDeviceFullyUpdated(): Boolean

    suspend fun areCvesPatched(
        cves: List<String>
    ): Boolean
}
Enter fullscreen mode Exit fullscreen mode

Then the implementation can encapsulate AndroidX Security State.

class DeviceSecurityRepositoryImpl(
    private val securityPatchState: SecurityPatchState
) : DeviceSecurityRepository {

    override suspend fun isDeviceFullyUpdated(): Boolean {
        return securityPatchState.isDeviceFullyUpdated()
    }

    override suspend fun areCvesPatched(
        cves: List<String>
    ): Boolean {
        return securityPatchState.areCvesPatched(cves)
    }
}
Enter fullscreen mode Exit fullscreen mode

API construction details can vary with the exact AndroidX release and integration environment, so check the current API reference before copying the constructor/setup code directly.

The important architectural idea is to keep the library behind your own repository boundary.


UseCase layer

With Clean Architecture:

class CheckDeviceSecurityUseCase(
    private val repository: DeviceSecurityRepository
) {

    suspend operator fun invoke(): Boolean {
        return repository.isDeviceFullyUpdated()
    }
}
Enter fullscreen mode Exit fullscreen mode

Now your ViewModel doesn't need to know anything about AndroidX Security State.


ViewModel

class SecurityViewModel(
    private val checkDeviceSecurity: CheckDeviceSecurityUseCase
) : ViewModel() {

    private val _isSecure = MutableStateFlow<Boolean?>(null)
    val isSecure = _isSecure.asStateFlow()

    fun checkSecurity() {
        viewModelScope.launch {
            _isSecure.value = checkDeviceSecurity()
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Jetpack Compose UI

The UI can remain extremely simple:

@Composable
fun SecurityScreen(
    viewModel: SecurityViewModel
) {
    val isSecure by viewModel.isSecure.collectAsState()

    when (isSecure) {
        null -> {
            CircularProgressIndicator()
        }

        true -> {
            Text("Device security is up to date")
        }

        false -> {
            Text("Security updates are available")
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Notice what is missing:

SecurityPatchState
Build.VERSION
CVE logic
OEM update logic
Enter fullscreen mode Exit fullscreen mode

None of that belongs inside the Composable.


CVE-aware security decisions

One of the most interesting capabilities is CVE verification.

Imagine a banking application has a policy requiring a specific vulnerability to be patched.

Conceptually:

User opens banking app
        |
        v
Check device security state
        |
        v
Are required CVEs patched?
       / \
     Yes  No
      |    |
      v    v
 Continue  Warning /
           restricted flow
Enter fullscreen mode Exit fullscreen mode

For example:

val requiredCves = listOf(
    "CVE-2026-XXXX"
)

val secure = repository.areCvesPatched(requiredCves)
Enter fullscreen mode Exit fullscreen mode

This can be much more meaningful than simply checking a date string.


Security policy should be centralized

Don't do this:

if (Build.VERSION.SECURITY_PATCH < "2026-09-01") {
    // block user
}
Enter fullscreen mode Exit fullscreen mode

inside five different screens.

Instead:

data class SecurityPolicyResult(
    val allowed: Boolean,
    val reason: String?
)
Enter fullscreen mode Exit fullscreen mode

and:

class EvaluateSecurityPolicyUseCase(
    private val repository: DeviceSecurityRepository
) {

    suspend operator fun invoke(): SecurityPolicyResult {

        val updated = repository.isDeviceFullyUpdated()

        return if (updated) {
            SecurityPolicyResult(
                allowed = true,
                reason = null
            )
        } else {
            SecurityPolicyResult(
                allowed = false,
                reason = "Security updates are available"
            )
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Now your business rules are testable.


Don't automatically block every outdated device

This is important.

A security-state API gives you information.

It does not mean every application should immediately refuse access when a device is not fully updated.

Your policy depends on your threat model.

For example:

News application

Outdated device
      |
      v
Allow access
      |
      v
Show optional security recommendation
Enter fullscreen mode Exit fullscreen mode

Enterprise application

Outdated device
      |
      v
Evaluate company policy
      |
      +----> Allow
      |
      +----> Restrict sensitive features
Enter fullscreen mode Exit fullscreen mode

Banking / high-security application

Outdated device
      |
      v
Check required CVEs
      |
      +----> Patched → Continue
      |
      +----> Not patched → Step-up / Restrict
Enter fullscreen mode Exit fullscreen mode

Security should be risk-based rather than blindly date-based.


Security State vs Play Integrity

These technologies solve different problems.

Capability Security State Play Integrity
Security patch state Yes Not the primary purpose
Available updates Yes No
CVE verification Yes No
Device/app integrity signals No Yes
Licensing / account abuse signals No No
Security posture Strong focus Different focus

In a high-security application, they can potentially complement each other rather than replace each other.


Security State vs Build.VERSION.SECURITY_PATCH

The old approach:

Build.VERSION.SECURITY_PATCH
Enter fullscreen mode Exit fullscreen mode

is still useful for simple compatibility or display logic.

But for a security policy:

Build.VERSION.SECURITY_PATCH
Enter fullscreen mode Exit fullscreen mode

should not automatically be treated as the complete security posture of the device.

A better architecture is:

Basic compatibility
        |
        v
Build.VERSION APIs

Security posture
        |
        v
AndroidX Security State
Enter fullscreen mode Exit fullscreen mode

What about Android 16?

Android 16 also adds several developer-facing security, performance, and system capabilities.

For example, Android 16 introduces system-triggered profiling for important events such as cold-start profiling and ANR-related traces, giving developers better visibility into production performance problems.

It also adds other platform improvements around accessibility, notifications, predictive back, adaptive refresh rate, and job diagnostics.

So Android 16 is not just another API-level bump.

It is increasingly giving developers better tools for understanding how their applications behave on real devices.


A security-aware Android architecture

For a modern Android application, I would structure security-related code like this:

app/
│
├── data/
│   └── security/
│       └── DeviceSecurityRepositoryImpl.kt
│
├── domain/
│   ├── model/
│   │   └── SecurityPolicyResult.kt
│   │
│   ├── repository/
│   │   └── DeviceSecurityRepository.kt
│   │
│   └── usecase/
│       ├── CheckDeviceSecurityUseCase.kt
│       └── EvaluateSecurityPolicyUseCase.kt
│
└── presentation/
    └── security/
        ├── SecurityViewModel.kt
        └── SecurityScreen.kt
Enter fullscreen mode Exit fullscreen mode

This is especially useful if you're already following:

MVVM
+
Clean Architecture
+
UseCase
+
Dependency Injection
Enter fullscreen mode Exit fullscreen mode

Testing strategy

Security code should be testable without requiring a real device for every test.

Test your policy separately:

@Test
fun `fully updated device is allowed`() = runTest {

    fakeRepository.isFullyUpdated = true

    val result = useCase()

    assertTrue(result.allowed)
}
Enter fullscreen mode Exit fullscreen mode

And:

@Test
fun `outdated device is restricted`() = runTest {

    fakeRepository.isFullyUpdated = false

    val result = useCase()

    assertFalse(result.allowed)
}
Enter fullscreen mode Exit fullscreen mode

Then keep AndroidX-specific integration tests separate.

This gives you:

Business-rule tests
        +
Android integration tests
Enter fullscreen mode Exit fullscreen mode

instead of coupling everything to a physical device.


When should you use AndroidX Security State?

It's particularly interesting for:

  • Banking applications
  • Fintech applications
  • Enterprise apps
  • Healthcare applications
  • MDM solutions
  • Security tools
  • Antivirus applications
  • Corporate device management
  • Apps handling highly sensitive data

For a normal consumer application, you may only need a lightweight security recommendation.


The bigger Android security trend

The interesting part isn't just one new AndroidX library.

The larger trend is:

Old Android security model

Patch Date
    ↓
Simple decision


Modern Android security model

Device State
    ↓
Component State
    ↓
Available Updates
    ↓
Vulnerability State
    ↓
Application Threat Model
    ↓
Security Policy
Enter fullscreen mode Exit fullscreen mode

That is a much better foundation for security-sensitive applications.


Key Takeaways

If you're an Android developer in 2026, these are the important points:

  1. Don't treat one patch-date string as the complete security posture.
  2. AndroidX Security State 1.1.0 is now stable.
  3. DSPL, PSPL, and ASPL provide more granular security information.
  4. CVE verification enables vulnerability-specific decisions.
  5. isDeviceFullyUpdated() can simplify high-level security checks.
  6. Keep security policy inside your domain layer.
  7. Don't put security decisions directly inside Compose UI.
  8. Don't block outdated devices without a clear threat model.
  9. Combine security signals when your application's risk justifies it.
  10. Test security policy independently from Android platform APIs.

Final Thoughts

Android security is moving toward a more detailed and actionable model.

Instead of asking:

"What is the device's security patch date?"

developers can increasingly ask:

"What security state is this device actually in, what updates are available, and are the vulnerabilities relevant to my application already patched?"

That shift is important for anyone building security-sensitive Android applications.

For Android developers working with Kotlin, Jetpack Compose, Clean Architecture, and modern security practices, AndroidX Security State is worth adding to your 2026 Android learning roadmap.


Official References


About the Author

Padmakar Garg is an Android Developer focused on Kotlin, Jetpack Compose, Clean Architecture, mobile security, system design, and open-source Android development.

He enjoys exploring how Android applications work beyond the UI layer — from networking and background processing to encryption, device security, performance, and scalable architecture.

Top comments (0)