public abstract class UpdateInfoService extends 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 methods

void
dump(FileDescriptor fd, PrintWriter writer, String[] args)

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 methods

abstract @NonNull List<@NonNull UpdateInfo>

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

int

Retrieves the UID of the calling process.

void

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

void

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

void

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

void

Called when a request completes.

boolean

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

boolean

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

Inherited methods

From android.content.Context
boolean
final int
getColor(int p0)
final @NonNull ColorStateList
final @Nullable Drawable
getDrawable(int p0)
final @NonNull String
getString(int p0)
final @NonNull String
getString(int p0, @NonNull Object... p1)
final @NonNull T
<T extends Object> getSystemService(@NonNull Class<@NonNull T> p0)
final @NonNull CharSequence
getText(int p0)
final @NonNull TypedArray
final @NonNull TypedArray
final @NonNull TypedArray
obtainStyledAttributes(int p0, @NonNull int[] p1)
final @NonNull TypedArray
obtainStyledAttributes(
    @Nullable AttributeSet p0,
    @NonNull int[] p1,
    int p2,
    int p3
)
void
void
sendBroadcastWithMultiplePermissions(
    @NonNull Intent p0,
    @NonNull String[] p1
)
From android.content.ContextWrapper
boolean
bindIsolatedService(
    @NonNull Intent p0,
    int p1,
    @NonNull String p2,
    @NonNull Executor p3,
    @NonNull ServiceConnection p4
)
boolean
boolean
boolean
boolean
bindService(
    @NonNull Intent p0,
    int p1,
    @NonNull Executor p2,
    @NonNull ServiceConnection p3
)
boolean
boolean
bindServiceAsUser(
    @NonNull Intent p0,
    @NonNull ServiceConnection p1,
    int p2,
    @NonNull UserHandle p3
)
int
int
@NonNull int[]
int
int
@NonNull int[]
int
checkContentUriPermissionFull(@NonNull Uri p0, int p1, int p2, int p3)
int
checkPermission(@NonNull String p0, int p1, int p2)
int
int
checkUriPermission(@NonNull Uri p0, int p1, int p2, int p3)
int
checkUriPermission(
    @Nullable Uri p0,
    @Nullable String p1,
    @Nullable String p2,
    int p3,
    int p4,
    int p5
)
@NonNull int[]
checkUriPermissions(@NonNull List<@NonNull Uri> p0, int p1, int p2, int p3)
void

This method is deprecated. Deprecated in Java

@NonNull Context
@NonNull Context
@NonNull Context
@NonNull Context
@NonNull Context
@NonNull Context
@NonNull Context
@NonNull Context
@NonNull Context
@NonNull Context
@NonNull String[]
boolean
boolean
boolean
void
void
enforceCallingOrSelfUriPermission(
    @NonNull Uri p0,
    int p1,
    @NonNull String p2
)
void
void
void
enforcePermission(@NonNull String p0, int p1, int p2, @Nullable String p3)
void
enforceUriPermission(
    @NonNull Uri p0,
    int p1,
    int p2,
    int p3,
    @NonNull String p4
)
void
enforceUriPermission(
    @Nullable Uri p0,
    @Nullable String p1,
    @Nullable String p2,
    int p3,
    int p4,
    int p5,
    @Nullable String p6
)
@NonNull String[]
@NonNull Context
@NonNull ApplicationInfo
@NonNull AssetManager
@NonNull AttributionSource
@Nullable String
@NonNull Context
@NonNull File
@NonNull ClassLoader
@NonNull File
@NonNull ContentResolver
@NonNull File
@NonNull File
int
@NonNull File
getDir(@NonNull String p0, int p1)
@Nullable Display
@Nullable File
@NonNull File[]
@Nullable File
@NonNull File[]
@NonNull File[]
@NonNull File
@NonNull File
@NonNull Executor
@NonNull Looper
@NonNull File
@NonNull File
@NonNull File[]
@NonNull String
@NonNull String
@NonNull PackageManager
@NonNull String
@NonNull String
@Nullable ContextParams
@NonNull Resources
@NonNull SharedPreferences
@NonNull Object
String
@NonNull Resources.Theme
@NonNull Drawable

This method is deprecated. Deprecated in Java

int

This method is deprecated. Deprecated in Java

int

This method is deprecated. Deprecated in Java

void
boolean
boolean
boolean
boolean
boolean
@NonNull FileInputStream
@NonNull FileOutputStream
openFileOutput(@NonNull String p0, int p1)
@NonNull SQLiteDatabase
openOrCreateDatabase(
    @NonNull String p0,
    int p1,
    @NonNull SQLiteDatabase.CursorFactory p2
)
@NonNull SQLiteDatabase
@NonNull Drawable

This method is deprecated. Deprecated in Java

void
void
Intent
Intent
registerReceiver(
    @Nullable BroadcastReceiver p0,
    @NonNull IntentFilter p1,
    int p2
)
Intent
registerReceiver(
    @Nullable BroadcastReceiver p0,
    @NonNull IntentFilter p1,
    @Nullable String p2,
    @Nullable Handler p3
)
Intent
registerReceiver(
    @Nullable BroadcastReceiver p0,
    @NonNull IntentFilter p1,
    @Nullable String p2,
    @Nullable Handler p3,
    int p4
)
void

This method is deprecated. Deprecated in Java

void

This method is deprecated. Deprecated in Java

void
void
void
void
void
void
void
void
void
void
sendOrderedBroadcast(
    @NonNull Intent p0,
    @Nullable String p1,
    @Nullable Bundle p2
)
void
sendOrderedBroadcast(
    @NonNull Intent p0,
    @Nullable String p1,
    @Nullable BroadcastReceiver p2,
    @Nullable Handler p3,
    int p4,
    @Nullable String p5,
    @Nullable Bundle p6
)
void
sendOrderedBroadcast(
    @NonNull Intent p0,
    @Nullable String p1,
    @Nullable Bundle p2,
    @Nullable BroadcastReceiver p3,
    @Nullable Handler p4,
    int p5,
    @Nullable String p6,
    @Nullable Bundle p7
)
void
sendOrderedBroadcast(
    @NonNull Intent p0,
    @Nullable String p1,
    @Nullable String p2,
    @Nullable BroadcastReceiver p3,
    @Nullable Handler p4,
    int p5,
    @Nullable String p6,
    @Nullable Bundle p7
)
void
sendOrderedBroadcast(
    @NonNull Intent p0,
    int p1,
    @Nullable String p2,
    @Nullable String p3,
    @Nullable BroadcastReceiver p4,
    @Nullable Handler p5,
    @Nullable String p6,
    @Nullable Bundle p7,
    @Nullable Bundle p8
)
void
sendOrderedBroadcastAsUser(
    @NonNull Intent p0,
    @NonNull UserHandle p1,
    @Nullable String p2,
    @Nullable BroadcastReceiver p3,
    @Nullable Handler p4,
    int p5,
    @Nullable String p6,
    @Nullable Bundle p7
)
void

This method is deprecated. Deprecated in Java

void

This method is deprecated. Deprecated in Java

void

This method is deprecated. Deprecated in Java

void
sendStickyOrderedBroadcast(
    @NonNull Intent p0,
    @Nullable BroadcastReceiver p1,
    @Nullable Handler p2,
    int p3,
    @Nullable String p4,
    @Nullable Bundle p5
)

This method is deprecated. Deprecated in Java

void
sendStickyOrderedBroadcastAsUser(
    @NonNull Intent p0,
    @NonNull UserHandle p1,
    @Nullable BroadcastReceiver p2,
    @Nullable Handler p3,
    int p4,
    @Nullable String p5,
    @Nullable Bundle p6
)

This method is deprecated. Deprecated in Java

void
setTheme(int p0)
void

This method is deprecated. Deprecated in Java

void

This method is deprecated. Deprecated in Java

void
startActivities(@NonNull Intent[] p0)
void
startActivities(@NonNull Intent[] p0, @Nullable Bundle p1)
void
void
@Nullable ComponentName
boolean
startInstrumentation(
    @NonNull ComponentName p0,
    @Nullable String p1,
    @Nullable Bundle p2
)
void
startIntentSender(
    @NonNull IntentSender p0,
    @Nullable Intent p1,
    int p2,
    int p3,
    int p4
)
void
startIntentSender(
    @NonNull IntentSender p0,
    @Nullable Intent p1,
    int p2,
    int p3,
    int p4,
    @Nullable Bundle p5
)
@Nullable ComponentName
boolean
void
void
void
void
void
updateServiceGroup(@NonNull ServiceConnection p0, int p1, int p2)
From android.app.Service
void
final @NonNull Application
final int
void
void
void
void

This method is deprecated.

void
void
onStart(@NonNull Intent p0, int p1)

This method is deprecated. Deprecated in Java

int
onStartCommand(@NonNull Intent p0, int p1, int p2)
void
void
onTimeout(int p0)
void
onTimeout(int p0, int p1)
void
onTrimMemory(int p0)
final void
final void
startForeground(int p0, @NonNull Notification p1, int p2)
final void
stopForeground(boolean p0)

This method is deprecated. Deprecated in Java

final void
final void
final void
stopSelf(int p0)
final boolean

Public constructors

UpdateInfoService

Added in 1.0.0-alpha02
public UpdateInfoService()

Public methods

dump

Added in 1.0.0-alpha02
public void dump(FileDescriptor fd, PrintWriter writer, String[] args)

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
public final IBinder onBind(Intent intent)

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
public final boolean onUnbind(Intent intent)

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 methods

fetchUpdates

protected abstract @NonNull List<@NonNull UpdateInfofetchUpdates()

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
@NonNull List<@NonNull UpdateInfo>

A list of UpdateInfo objects currently available for the device.

getCallerUid

Added in 1.0.0-alpha02
protected int getCallerUid()

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 void onClientConnected(@NonNull Intent intent)

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
@NonNull Intent intent

The Intent that was used to bind to this service.

onClientDisconnected

Added in 1.0.0-alpha02
protected void onClientDisconnected(Intent intent)

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 void onFetchFailed(@NonNull Exception e)

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
@NonNull Exception e

The exception thrown during the operation.

onRequestCompleted

Added in 1.0.0-alpha02
protected void onRequestCompleted(@NonNull UpdateCheckTelemetry telemetry)

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
@NonNull UpdateCheckTelemetry telemetry

The UpdateCheckTelemetry containing metrics and outcomes.

shouldFetchUpdates

Added in 1.0.0-alpha02
protected boolean shouldFetchUpdates()

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 boolean shouldThrottle()

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.