abstract class UpdateInfoService : Service


Base class for implementing the AndroidX Security State Update Provider service.

This abstract class provides the foundational implementation for the IUpdateInfoService AIDL interface. It manages the complexity of serving security update information to client applications, enforcing a consistent contract for data freshness, resource usage, and observability.

Responsibilities

  • IPC Handling: Manages the AIDL binding process and verifies Intent actions.

  • Concurrency Control: Implements Double-Checked Locking to prevent "thundering herd" scenarios where multiple clients trigger parallel network requests.

  • Rate Limiting: Enforces a default throttling policy (e.g., maximum one check per hour) to protect backend infrastructure.

  • Caching: Automatically persists fetched results and freshness metadata to local storage.

Monitoring & Telemetry

To support high-scale hosts that require strict monitoring, this class provides a comprehensive set of observability hooks. Hosts can override these methods to integrate with their own logging infrastructure:

Host Implementation

Host applications (such as the System Updater, Google Play Store, or OEM-specific updaters) must extend this class and implement the fetchUpdates method to provide the actual network logic.

Manifest Declaration

To expose this service, you must declare it in your AndroidManifest.xml with the exported="true" attribute and an intent-filter for the UPDATE_INFO_SERVICE action:

<service
android:name=".MyUpdateInfoService"
android:exported="true">
<intent-filter>
<action android:name="androidx.security.state.provider.UPDATE_INFO_SERVICE" />
</intent-filter>
</service>

Summary

Public constructors

Public functions

open Unit
dump(fd: FileDescriptor?, writer: PrintWriter?, args: Array<String>?)

Dumps the state of the service for debugging (e.g. adb shell dumpsys activity service).

final IBinder?
onBind(intent: Intent?)

Called by the system when a client binds to the particular interface defined by the intent.

final Boolean
onUnbind(intent: Intent?)

Called by the system when all clients have disconnected from the particular interface defined by the intent.

Protected functions

abstract suspend List<UpdateInfo>

Performs the actual network request to fetch fresh updates from the backend.

open Int

Retrieves the UID of the calling process.

open Unit

Called when a client binds to the particular interface defined by the intent.

open Unit

Called when all clients have disconnected from the particular interface defined by the intent.

open Unit

Callback for handling exceptions that occur during the update check process.

open Unit

Called when a request completes.

open Boolean

Determines if the local cache is stale and a refresh should be attempted.

open Boolean

Checks if the operation should be throttled based on the rate limiter.

Inherited functions

From android.content.Context
From android.content.ContextWrapper
open Boolean
bindIsolatedService(
    p0: Intent,
    p1: Int,
    p2: String,
    p3: Executor,
    p4: ServiceConnection
)
open Boolean
bindService(
    p0: Intent,
    p1: ServiceConnection,
    p2: Context.BindServiceFlags
)
open Boolean
open Boolean
bindService(
    p0: Intent,
    p1: Context.BindServiceFlags,
    p2: Executor,
    p3: ServiceConnection
)
open Boolean
bindService(p0: Intent, p1: Int, p2: Executor, p3: ServiceConnection)
open Boolean
bindServiceAsUser(
    p0: Intent,
    p1: ServiceConnection,
    p2: Context.BindServiceFlags,
    p3: UserHandle
)
open Boolean
open Int
open Int
open IntArray
open Int
open Int
open IntArray
open Int
checkContentUriPermissionFull(p0: Uri, p1: Int, p2: Int, p3: Int)
open Int
checkPermission(p0: String, p1: Int, p2: Int)
open Int
open Int
checkUriPermission(p0: Uri, p1: Int, p2: Int, p3: Int)
open Int
checkUriPermission(p0: Uri?, p1: String?, p2: String?, p3: Int, p4: Int, p5: Int)
open IntArray
checkUriPermissions(p0: MutableList<Uri>, p1: Int, p2: Int, p3: Int)
open Unit

This function is deprecated. Deprecated in Java

open Context
open Context
open Context
open Context
open Context
open Context
open Context
open Context
open Context
open Context
createWindowContext(p0: Display, p1: Int, p2: Bundle?)
open Array<String>
open Boolean
open Boolean
open Boolean
open Unit
open Unit
open Unit
open Unit
open Unit
enforcePermission(p0: String, p1: Int, p2: Int, p3: String?)
open Unit
enforceUriPermission(p0: Uri, p1: Int, p2: Int, p3: Int, p4: String)
open Unit
enforceUriPermission(
    p0: Uri?,
    p1: String?,
    p2: String?,
    p3: Int,
    p4: Int,
    p5: Int,
    p6: String?
)
open Array<String>
open Context
open ApplicationInfo
open AssetManager
open AttributionSource
open String?
open Context
open File
open ClassLoader
open File
open ContentResolver
open File
open File
open Int
open File
getDir(p0: String, p1: Int)
open Display?
open File?
open Array<File>
open File?
open Array<File>
open Array<File>
open File
open File
open Executor
open Looper
open File
open File
open Array<File>
open String
open String
open PackageManager
open String
open String
open ContextParams?
open Resources
open SharedPreferences
open Any
open String?
open Resources.Theme
open Drawable

This function is deprecated. Deprecated in Java

open Int

This function is deprecated. Deprecated in Java

open Int

This function is deprecated. Deprecated in Java

open Unit
grantUriPermission(p0: String, p1: Uri, p2: Int)
open Boolean
open Boolean
open Boolean
open Boolean
open Boolean
open FileInputStream
open FileOutputStream
open SQLiteDatabase
open SQLiteDatabase
openOrCreateDatabase(
    p0: String,
    p1: Int,
    p2: SQLiteDatabase.CursorFactory,
    p3: DatabaseErrorHandler?
)
open Drawable

This function is deprecated. Deprecated in Java

open Unit
open Unit
open Intent?
open Intent?
open Intent?
registerReceiver(
    p0: BroadcastReceiver?,
    p1: IntentFilter,
    p2: String?,
    p3: Handler?
)
open Intent?
registerReceiver(
    p0: BroadcastReceiver?,
    p1: IntentFilter,
    p2: String?,
    p3: Handler?,
    p4: Int
)
open Unit

This function is deprecated. Deprecated in Java

open Unit

This function is deprecated. Deprecated in Java

open Unit
open Unit
open Unit
revokeUriPermission(p0: String, p1: Uri, p2: Int)
open Unit
open Unit
open Unit
sendBroadcast(p0: Intent, p1: String?, p2: Bundle?)
open Unit
open Unit
open Unit
open Unit
open Unit
sendOrderedBroadcast(
    p0: Intent,
    p1: String?,
    p2: BroadcastReceiver?,
    p3: Handler?,
    p4: Int,
    p5: String?,
    p6: Bundle?
)
open Unit
sendOrderedBroadcast(
    p0: Intent,
    p1: String?,
    p2: Bundle?,
    p3: BroadcastReceiver?,
    p4: Handler?,
    p5: Int,
    p6: String?,
    p7: Bundle?
)
open Unit
sendOrderedBroadcast(
    p0: Intent,
    p1: String?,
    p2: String?,
    p3: BroadcastReceiver?,
    p4: Handler?,
    p5: Int,
    p6: String?,
    p7: Bundle?
)
open Unit
sendOrderedBroadcast(
    p0: Intent,
    p1: Int,
    p2: String?,
    p3: String?,
    p4: BroadcastReceiver?,
    p5: Handler?,
    p6: String?,
    p7: Bundle?,
    p8: Bundle?
)
open Unit
sendOrderedBroadcastAsUser(
    p0: Intent,
    p1: UserHandle,
    p2: String?,
    p3: BroadcastReceiver?,
    p4: Handler?,
    p5: Int,
    p6: String?,
    p7: Bundle?
)
open Unit

This function is deprecated. Deprecated in Java

open Unit

This function is deprecated. Deprecated in Java

open Unit

This function is deprecated. Deprecated in Java

open Unit
sendStickyOrderedBroadcast(
    p0: Intent,
    p1: BroadcastReceiver?,
    p2: Handler?,
    p3: Int,
    p4: String?,
    p5: Bundle?
)

This function is deprecated. Deprecated in Java

open Unit
sendStickyOrderedBroadcastAsUser(
    p0: Intent,
    p1: UserHandle,
    p2: BroadcastReceiver?,
    p3: Handler?,
    p4: Int,
    p5: String?,
    p6: Bundle?
)

This function is deprecated. Deprecated in Java

open Unit
open Unit

This function is deprecated. Deprecated in Java

open Unit

This function is deprecated. Deprecated in Java

open Unit
open Unit
open Unit
open Unit
open ComponentName?
open Boolean
open Unit
startIntentSender(p0: IntentSender, p1: Intent?, p2: Int, p3: Int, p4: Int)
open Unit
startIntentSender(
    p0: IntentSender,
    p1: Intent?,
    p2: Int,
    p3: Int,
    p4: Int,
    p5: Bundle?
)
open ComponentName?
open Boolean
open Unit
open Unit
open Unit
open Unit
open Unit
From android.app.Service
open Unit
Application
Int
open Unit
open Unit
open Unit
open Unit

This function is deprecated.

open Unit
open Unit
onStart(p0: Intent, p1: Int)

This function is deprecated. Deprecated in Java

open Int
onStartCommand(p0: Intent, p1: Int, p2: Int)
open Unit
open Unit
open Unit
onTimeout(p0: Int, p1: Int)
open Unit
Unit
Unit
startForeground(p0: Int, p1: Notification, p2: Int)
Unit

This function is deprecated. Deprecated in Java

Unit
Unit
Unit
Boolean

Public constructors

UpdateInfoService

Added in 1.0.0-alpha02
UpdateInfoService()

Public functions

dump

Added in 1.0.0-alpha02
open fun dump(fd: FileDescriptor?, writer: PrintWriter?, args: Array<String>?): Unit

Dumps the state of the service for debugging (e.g. adb shell dumpsys activity service).

This implementation provides a snapshot of the internal state, including:

  • Active Request Count: To detect stuck threads or high concurrency.

  • Global Last Check Time: The timestamp of the last successful service-wide sync (Service Health).

  • Throttling Status: Whether the rate limiter is currently blocking network requests.

  • Cached Updates: A complete list of stored updates with detailed metadata (Component, SPL, Provider, Published Date, Last Checked Time).

onBind

Added in 1.0.0-alpha02
final fun onBind(intent: Intent?): IBinder?

Called by the system when a client binds to the particular interface defined by the intent.

This method verifies that the Intent action matches the expected contract (ACTION_BIND). If the action is missing or incorrect, the binding is rejected to ensure the service is not exposed unintentionally.

Lifecycle Note: Because the client library attaches unique data (the package name) to the intent, this method is called for every new client session, allowing the onClientConnected hook to reliably track individual connections.

Parameters
intent: Intent?

The Intent that was used to bind to this service.

Returns
IBinder?

The IBinder interface for clients to interact with the service, or null if the Intent action is invalid.

onUnbind

Added in 1.0.0-alpha02
final fun onUnbind(intent: Intent?): Boolean

Called by the system when all clients have disconnected from the particular interface defined by the intent.

This method is marked final to enforce the library's lifecycle contract. It performs two critical actions:

  1. Triggers the onClientDisconnected hook, allowing the host to log the end of the session.

  2. Returns false, which forces the Android system to call onBind (and thus onClientConnected) for all future connections. This simplifies telemetry by ensuring a consistent "Connect -> Disconnect" cycle without needing to handle the onRebind edge case.

Parameters
intent: Intent?

The Intent that was used to bind to this service.

Returns
Boolean

false to ensure onRebind is not called.

Protected functions

fetchUpdates

protected abstract suspend fun fetchUpdates(): List<UpdateInfo>

Performs the actual network request to fetch fresh updates from the backend.

Implementations of this method should:

  • Block until the network request completes.

  • Return the list of updates found.

  • Throw an exception if the network request fails (this will be caught and logged).

Note: This method is only called if shouldFetchUpdates returns true and the rate limiter allows the request.

Returns
List<UpdateInfo>

A list of UpdateInfo objects currently available for the device.

getCallerUid

Added in 1.0.0-alpha02
protected open fun getCallerUid(): Int

Retrieves the UID of the calling process.

The default implementation delegates to android.os.Binder.getCallingUid. Host implementations using a proxy or broker architecture should override this to return the logical client UID instead of the broker's UID, ensuring correct attribution.

onClientConnected

Added in 1.0.0-alpha02
protected open fun onClientConnected(intent: Intent): Unit

Called when a client binds to the particular interface defined by the intent.

This method is invoked during onBind after the Intent action has been verified.

Usage: Override this method to log connection metrics (e.g., "Session Started") or track adoption trends.

Client Identity: The intent passed to this method typically contains the client's package name in the data URI (e.g., package:com.example.client). This allows you to identify which app is starting a session. Note that this value is self-reported by the client library and is useful for aggregate trends but less secure than the UpdateCheckTelemetry.callerUid captured in onRequestCompleted.

Lifecycle: Because the client library attaches unique data to the bind Intent, this method is called for every new client session, enabling accurate session counting.

Parameters
intent: Intent

The Intent that was used to bind to this service.

onClientDisconnected

Added in 1.0.0-alpha02
protected open fun onClientDisconnected(intent: Intent?): Unit

Called when all clients have disconnected from the particular interface defined by the intent.

This method is invoked during onUnbind.

Usage: Override this method to log session ends (e.g., "Session Ended") to calculate session duration when paired with onClientConnected. You can also use this to perform per-client resource cleanup.

Parameters
intent: Intent?

The Intent that was used to bind to this service. It contains the same identification data as passed to onClientConnected.

onFetchFailed

Added in 1.0.0-alpha02
protected open fun onFetchFailed(e: Exception): Unit

Callback for handling exceptions that occur during the update check process.

This method is invoked if any step of the update logic fails, including:

  • Determining cache freshness (shouldFetchUpdates).

  • Recording rate-limit attempts.

  • Fetching data from the backend (fetchUpdates).

  • Persisting the results to local storage.

The default implementation logs the error to Logcat. Hosts can override this to report errors to their own telemetry or crash reporting systems.

Parameters
e: Exception

The exception thrown during the operation.

onRequestCompleted

Added in 1.0.0-alpha02
protected open fun onRequestCompleted(telemetry: UpdateCheckTelemetry): Unit

Called when a request completes. Override this to log telemetry.

This hook is called for every request to listAvailableUpdates, regardless of whether it succeeded, failed, was throttled, or was served from the cache.

Usage: Use this hook to log granular performance metrics (latency histograms) and resource usage.

Attribution: The telemetry object contains the UpdateCheckTelemetry.callerUid, which is the Kernel-verified UID of the calling process. This is the authoritative source for attributing load (CPU/Network/Lock Contention) to specific client applications.

Parameters
telemetry: UpdateCheckTelemetry

The UpdateCheckTelemetry containing metrics and outcomes.

shouldFetchUpdates

Added in 1.0.0-alpha02
protected open fun shouldFetchUpdates(): Boolean

Determines if the local cache is stale and a refresh should be attempted.

The default implementation returns true if the data is older than 1 hour. Hosts can override this to implement custom caching policies (e.g., 4 hours, 24 hours).

Returns
Boolean

true if a network fetch should be attempted.

shouldThrottle

Added in 1.0.0-alpha02
protected open fun shouldThrottle(): Boolean

Checks if the operation should be throttled based on the rate limiter.

The default implementation delegates to an internal rate limiter that enforces a cooling-off period (e.g., one check per hour). Hosts can override this to inject custom rate limiting logic (e.g., battery checks).

Returns
Boolean

true if the request should be blocked.