Chapter 20: system_server¶
Overview¶
The system_server process is the beating heart of the Android framework. Born
from Zygote during early boot, it hosts over one hundred Java system services
that collectively manage every aspect of the device: activities, windows,
packages, power, networking, notifications, input, display, audio, security,
and much more. Every Android app interacts with system_server dozens of
times per second through Binder IPC, even if the developer never writes a
single line of code that mentions it.
This chapter traces system_server from its creation by Zygote through its
multi-phase boot sequence, catalogs the services it hosts, explains its
threading model, examines the Watchdog that guards against deadlocks, and
provides hands-on exercises for inspecting a live system.
Key source files for this chapter:
| File | Description |
|---|---|
frameworks/base/services/java/com/android/server/SystemServer.java |
Entry point and service startup orchestration |
frameworks/base/services/core/java/com/android/server/SystemService.java |
Base class for all system services |
frameworks/base/services/core/java/com/android/server/SystemServiceManager.java |
Manages service lifecycle and boot phases |
frameworks/base/services/core/java/com/android/server/Watchdog.java |
Deadlock detection and recovery |
frameworks/base/core/java/com/android/server/ServiceThread.java |
Base class for named handler threads |
frameworks/base/services/core/java/com/android/server/DisplayThread.java |
Display-priority shared thread |
frameworks/base/services/core/java/com/android/server/AnimationThread.java |
Animation-priority shared thread |
frameworks/base/core/java/com/android/server/FgThread.java |
Foreground shared thread |
frameworks/base/services/core/java/com/android/server/IoThread.java |
I/O shared thread |
frameworks/base/services/core/java/com/android/server/UiThread.java |
UI shared thread |
frameworks/base/core/java/com/android/internal/os/BackgroundThread.java |
Background shared thread |
20.1 The system_server Process¶
20.1.1 Birth from Zygote¶
When the Android runtime starts, init launches app_process which creates
the Zygote process. Zygote preloads common classes and resources, then
forks system_server as its very first child. This fork-based creation
gives system_server an enormous head start: all preloaded framework classes,
common libraries, and shared resources are already mapped into its address
space via copy-on-write memory.
The entry point in SystemServer.java is minimal. At line 710:
// frameworks/base/services/java/com/android/server/SystemServer.java, line 710
public static void main(String[] args) {
new SystemServer().run();
}
The constructor records basic start information (line 714-727):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 714
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
// Record process start information.
mStartCount = SystemProperties.getInt(SYSPROP_START_COUNT, 0) + 1;
mRuntimeStartElapsedTime = SystemClock.elapsedRealtime();
mRuntimeStartUptime = SystemClock.uptimeMillis();
Process.setStartTimes(mRuntimeStartElapsedTime, mRuntimeStartUptime,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
// Remember if it's runtime restart or reboot.
mRuntimeRestart = mStartCount > 1;
}
The mStartCount field tracks how many times system_server has started.
A value greater than 1 indicates a runtime restart rather than a fresh boot --
an important distinction because a runtime restart skips certain one-time
initialization steps.
20.1.2 The run() Method -- Initializing the World¶
The run() method (line 836) is where all initialization happens. It follows
a carefully ordered sequence:
run()
|
+-- InitBeforeStartServices
| +-- Record start info in system properties
| +-- Initialize time zone
| +-- Set Binder to warn on blocking calls
| +-- Configure SQLite defaults
| +-- Prepare main looper
| +-- Start SystemServerInitThreadPool
| +-- Enqueue SystemConfig loading
| +-- Load libandroid_servers.so
| +-- Spawn fd leak check thread (debug builds)
| +-- Check for pending shutdown
| +-- Create system context
| +-- Create SystemServiceManager
|
+-- Start services
| +-- startBootstrapServices()
| +-- startCoreServices()
| +-- startOtherServices()
| +-- startApexServices()
| +-- updateWatchdogTimeout()
|
+-- Enter Looper.loop() -- runs forever
Several critical early steps deserve attention.
Binder thread pool configuration (line 932):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 493
private static final int sMaxBinderThreads = 31;
// ...
// line 932
BinderInternal.setMaxThreads(sMaxBinderThreads);
The system_server raises its Binder thread pool to 31 threads, well above the
default of 15 for regular apps. This is necessary because system_server
simultaneously serves hundreds of client processes.
Main looper preparation (line 934-939):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 934
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
Looper.prepareMainLooper();
Looper.getMainLooper().setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
The main thread gets foreground priority, and its looper is configured to log warnings for messages taking longer than 100ms to dispatch or 200ms to deliver. These thresholds help identify performance problems.
System context creation (line 1160-1168):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1160
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
final Context systemUiContext = activityThread.getSystemUiContext();
systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
Trace.registerWithPerfetto();
}
Even though system_server is not a typical Android app, it needs an
ActivityThread and a Context for accessing resources, databases,
content providers, and the rest of the framework APIs.
SystemServiceManager creation (line 978-983):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 978
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
mDumper.addDumpable(mSystemServiceManager);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
The SystemServiceManager is the central coordinator. It maintains the list
of all started SystemService instances, drives boot phase transitions,
and dispatches user lifecycle events. It is published as a local service
so any code within system_server can access it without Binder.
20.1.3 Service Module Organization¶
The frameworks/base/services/ directory contains 59 modules organized by
functional area. The main module is services/java/ which contains
SystemServer.java itself. The core module services/core/ hosts the
majority of services, with 74 Java files and 102 subdirectory packages
directly under com.android.server:
frameworks/base/services/
+-- java/ # SystemServer.java entry point
+-- core/ # Core services (102 sub-packages)
+-- accessibility/ # AccessibilityManagerService
+-- appfunctions/ # AppFunctionManagerService
+-- appprediction/ # AppPredictionManagerService
+-- appwidget/ # AppWidgetService
+-- autofill/ # AutofillManagerService
+-- backup/ # BackupManagerService
+-- companion/ # CompanionDeviceManagerService
+-- contentcapture/ # ContentCaptureManagerService
+-- contentsuggestions/ # ContentSuggestionsManagerService
+-- contextualsearch/ # ContextualSearchManagerService
+-- coverage/ # CoverageService
+-- credentials/ # CredentialManagerService
+-- devicepolicy/ # DevicePolicyManagerService
+-- flags/ # FeatureFlagsService
+-- midi/ # MidiService
+-- musicrecognition/ # MusicRecognitionManagerService
+-- net/ # NetworkManagementService
+-- people/ # PeopleService
+-- permission/ # AccessCheckingService
+-- print/ # PrintManagerService
+-- profcollect/ # ProfcollectForwardingService
+-- restrictions/ # RestrictionsManagerService
+-- searchui/ # SearchUiManagerService
+-- selectiontoolbar/ # SelectionToolbarManagerService
+-- serial/ # SerialManagerService
+-- smartspace/ # SmartspaceManagerService
+-- supervision/ # SupervisionService
+-- systemcaptions/ # SystemCaptionsManagerService
+-- texttospeech/ # TextToSpeechManagerService
+-- translation/ # TranslationManagerService
+-- usage/ # UsageStatsService, StorageStatsService
+-- usb/ # UsbService
+-- voiceinteraction/ # VoiceInteractionManagerService
+-- wifi/ # (managed via APEX jar)
+-- ... (59 total entries)
20.1.4 The Four Startup Phases¶
After initialization, SystemServer.run() calls four methods in strict
sequence (lines 1031-1034):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1024
// Start services.
try {
t.traceBegin("StartServices");
// ...
startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
startApexServices(t);
// ...
}
After all services are started, the main thread enters Looper.loop() at
line 1081 and never returns:
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1080
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
The following Mermaid diagram shows the complete lifecycle:
graph TD
A["Zygote forks system_server"] --> B["SystemServer.main()"]
B --> C["SystemServer.run()"]
C --> D["InitBeforeStartServices"]
D --> D1["Prepare main Looper"]
D --> D2["Load libandroid_servers.so"]
D --> D3["Create system Context"]
D --> D4["Create SystemServiceManager"]
D4 --> E["startBootstrapServices()"]
E --> F["startCoreServices()"]
F --> G["startOtherServices()"]
G --> H["startApexServices()"]
H --> I["updateWatchdogTimeout()"]
I --> J["Looper.loop() -- runs forever"]
style A fill:#f9f,stroke:#333
style J fill:#9f9,stroke:#333
20.2 Service Lifecycle¶
20.2.1 The SystemService Base Class¶
Every service running inside system_server extends the abstract
SystemService class, defined in:
The class is annotated @SystemApi(client = Client.SYSTEM_SERVER), making
it a stable API surface for system server modules. Its core structure is
straightforward (lines 72, 337-360):
// frameworks/base/services/core/java/com/android/server/SystemService.java, line 72
@SystemApi(client = Client.SYSTEM_SERVER)
public abstract class SystemService {
private final Context mContext;
private final List<Class<?>> mDependencies;
// line 337
public SystemService(@NonNull Context context) {
this(context, Collections.emptyList());
}
// line 357
public SystemService(@NonNull Context context,
@NonNull List<Class<?>> dependencies) {
mContext = context;
mDependencies = Objects.requireNonNull(dependencies);
}
The dependencies list is used by the Ravenwood deviceless testing
environment to understand transitive dependencies needed to support a
specific test. In production, most services pass an empty list.
20.2.2 Lifecycle Callbacks¶
SystemService defines the following lifecycle callbacks:
| Callback | When called | Purpose |
|---|---|---|
onStart() |
Service creation | Publish binder interfaces via publishBinderService() |
onBootPhase(int) |
Each boot phase | React to system readiness milestones |
onUserStarting(TargetUser) |
User starts | Initialize per-user state |
onUserUnlocking(TargetUser) |
User unlocking | Access credential-encrypted storage |
onUserUnlocked(TargetUser) |
User unlocked | Post-unlock initialization |
onUserSwitching(from, to) |
User switch | Transfer foreground user state |
onUserStopping(TargetUser) |
User stopping | Last chance for CE storage access |
onUserStopped(TargetUser) |
User stopped | Final cleanup after process teardown |
onUserCompletedEvent(TargetUser, type) |
After user events complete | Deferred non-urgent processing |
The onStart() method is the only abstract method (line 412):
// frameworks/base/services/core/java/com/android/server/SystemService.java, line 412
public abstract void onStart();
All other callbacks have empty default implementations, allowing services to override only what they need.
Important note from the source (line 65-66):
NOTE: All lifecycle methods are called from the system server's main looper thread.
This means lifecycle callbacks must not block. Long-running initialization must be dispatched to background threads.
20.2.3 Publishing Services¶
SystemService provides three mechanisms for publishing interfaces:
1. Binder service -- accessible by other processes via ServiceManager
(line 578-608):
// frameworks/base/services/core/java/com/android/server/SystemService.java, line 578
protected final void publishBinderService(@NonNull String name,
@NonNull IBinder service) {
publishBinderService(name, service, false);
}
// line 606
protected final void publishBinderService(String name, IBinder service,
boolean allowIsolated, int dumpPriority) {
ServiceManager.addService(name, service, allowIsolated, dumpPriority);
}
2. Local service -- accessible only within system_server via
LocalServices (line 625-627):
// frameworks/base/services/core/java/com/android/server/SystemService.java, line 625
protected final <T> void publishLocalService(Class<T> type, T service) {
LocalServices.addService(type, service);
}
Local services avoid Binder IPC overhead for intra-process communication. Many services publish both a Binder interface (for apps) and a local interface (for other system services).
3. Direct registration -- some services bypass SystemService and
register directly with ServiceManager.addService(). This older pattern
is still used by services that predate the SystemService framework.
20.2.4 Boot Phases¶
Boot phases allow services to synchronize their initialization with the
overall system readiness. Each phase is a numeric constant, and services
receive them in ascending order. The phases defined in SystemService.java
(lines 80-124):
| Phase | Value | Constant | Meaning |
|---|---|---|---|
| Wait for default display | 100 | PHASE_WAIT_FOR_DEFAULT_DISPLAY |
Display manager has provided the default display |
| Wait for sensor service | 200 | PHASE_WAIT_FOR_SENSOR_SERVICE |
SensorService is available (hidden, internal) |
| Lock settings ready | 480 | PHASE_LOCK_SETTINGS_READY |
Lock settings data can be obtained |
| System services ready | 500 | PHASE_SYSTEM_SERVICES_READY |
Core services like PowerManager and PackageManager are safe to call |
| Device-specific services ready | 520 | PHASE_DEVICE_SPECIFIC_SERVICES_READY |
OEM/device-specific services are available |
| Activity manager ready | 550 | PHASE_ACTIVITY_MANAGER_READY |
Services can broadcast Intents |
| Third-party apps can start | 600 | PHASE_THIRD_PARTY_APPS_CAN_START |
Apps can make Binder calls into services |
| Boot completed | 1000 | PHASE_BOOT_COMPLETED |
Boot is complete, home app has started |
The SystemServiceManager dispatches phases to all registered services:
graph LR
A["PHASE_WAIT_FOR_DEFAULT_DISPLAY<br/>100"] --> B["PHASE_WAIT_FOR_SENSOR_SERVICE<br/>200"]
B --> C["PHASE_LOCK_SETTINGS_READY<br/>480"]
C --> D["PHASE_SYSTEM_SERVICES_READY<br/>500"]
D --> E["PHASE_DEVICE_SPECIFIC_SERVICES_READY<br/>520"]
E --> F["PHASE_ACTIVITY_MANAGER_READY<br/>550"]
F --> G["PHASE_THIRD_PARTY_APPS_CAN_START<br/>600"]
G --> H["PHASE_BOOT_COMPLETED<br/>1000"]
style A fill:#fdd,stroke:#333
style D fill:#ffd,stroke:#333
style H fill:#dfd,stroke:#333
The boot phases form a contract: a service that needs to call
PowerManager should wait until PHASE_SYSTEM_SERVICES_READY (500),
while a service that needs to start third-party app components should wait
until PHASE_THIRD_PARTY_APPS_CAN_START (600).
20.2.5 TargetUser and User Lifecycle¶
The TargetUser inner class (lines 147-246) wraps user information for
lifecycle callbacks:
// frameworks/base/services/core/java/com/android/server/SystemService.java, line 147
public static final class TargetUser {
private final @UserIdInt int mUserId;
private final boolean mFull;
private final boolean mProfile;
private final String mUserType;
private final boolean mPreCreated;
// ...
}
Services can override isUserSupported(TargetUser) (line 428) to opt out of
lifecycle callbacks for specific user types. For example, a service that
only works for full users (not profiles) can return false for profile
users, avoiding unnecessary per-user initialization.
The UserCompletedEventType (lines 254-326) allows batched notification
of completed user events. This is a performance optimization -- services
that need to react to multiple user events can handle them together in
onUserCompletedEvent() rather than individually.
20.2.6 The SystemServiceManager¶
The SystemServiceManager (defined in SystemServiceManager.java,
lines 75-138) is the orchestrator:
// frameworks/base/services/core/java/com/android/server/SystemServiceManager.java, line 75
public final class SystemServiceManager implements Dumpable {
private List<SystemService> mServices;
private Set<String> mServiceClassnames;
private int mCurrentPhase = -1;
// ...
}
It provides several startService() variants:
- By class --
startService(Class<T>)-- for services inservices.jar - By class name --
startService(String)-- for services on the system server classpath but not inservices.jar - From JAR --
startServiceFromJar(String, String)-- for services in standalone APEX JARs (like WiFi, Bluetooth, Connectivity)
The JAR-based loading (line 167-173) uses PathClassLoader:
// frameworks/base/services/core/java/com/android/server/SystemServiceManager.java, line 167
public SystemService startServiceFromJar(String className, String path) {
PathClassLoader pathClassLoader =
SystemServerClassLoaderFactory.getOrCreateClassLoader(
path, this.getClass().getClassLoader(), isJarInTestApex(path));
final Class<SystemService> serviceClass =
loadClassFromLoader(className, pathClassLoader);
return startService(serviceClass);
}
This modular loading allows mainline modules (WiFi, Bluetooth, Connectivity, UWB) to deliver their system services via APEXes rather than being compiled into the platform monolith.
20.3 Key Services Catalog¶
20.3.1 Bootstrap Services¶
Bootstrap services form the critical dependency chain. They have circular
dependencies that prevent simple sequential initialization, which is why
they are started in a special startBootstrapServices() method. Listed in
start order from SystemServer.java:
| # | Service | Class | Purpose |
|---|---|---|---|
| 1 | Watchdog | Watchdog |
Deadlock detection (started first) |
| 2 | PlatformCompat | PlatformCompat |
App compatibility framework |
| 3 | FileIntegrityService | FileIntegrityService |
fs-verity support |
| 4 | Installer | Installer |
Package installation daemon interface |
| 5 | DeviceIdentifiersPolicyService | DeviceIdentifiersPolicyService |
Device ID access policy |
| 6 | FeatureFlagsService | FeatureFlagsService |
Runtime flag overrides |
| 7 | UriGrantsManagerService | UriGrantsManagerService.Lifecycle |
Content URI permission grants |
| 8 | PowerStatsService | PowerStatsService |
Rail power data tracking |
| 9 | AccessCheckingService | AccessCheckingService |
Permissions and app-ops |
| 10 | ActivityTaskManagerService | ActivityTaskManagerService.Lifecycle |
Activity/task management |
| 11 | ActivityManagerService | ActivityManagerService.Lifecycle |
Process lifecycle management |
| 12 | DataLoaderManagerService | DataLoaderManagerService |
Incremental data loading |
| 13 | PowerManagerService | PowerManagerService |
Power state management |
| 14 | ThermalManagerService | ThermalManagerService |
Thermal throttling |
| 15 | RecoverySystemService | RecoverySystemService.Lifecycle |
OTA and recovery |
| 16 | LightsService | LightsService |
LED and backlight control |
| 17 | DisplayManagerService | DisplayManagerService |
Display management |
| 18 | DomainVerificationService | DomainVerificationService |
App link verification |
| 19 | PackageManagerService | PackageManagerService |
Package/APK management |
| 20 | UserManagerService | UserManagerService.LifeCycle |
Multi-user management |
| 21 | OverlayManagerService | OverlayManagerService |
Runtime resource overlays |
| 22 | ResourcesManagerService | ResourcesManagerService |
Resource package management |
| 23 | SensorPrivacyService | SensorPrivacyService |
Camera/mic privacy toggles |
| 24 | SensorService | SensorService |
Sensor HAL interface |
20.3.2 Core Services¶
Core services are not entangled in the bootstrap dependency web but are
still essential. From startCoreServices():
| # | Service | Class | Purpose |
|---|---|---|---|
| 1 | SystemConfigService | SystemConfigService |
System configuration |
| 2 | BatteryService | BatteryService |
Battery level tracking |
| 3 | UsageStatsService | UsageStatsService |
App usage statistics |
| 4 | WebViewUpdateService | WebViewUpdateService |
WebView provider management |
| 5 | CachedDeviceStateService | CachedDeviceStateService |
Device state caching |
| 6 | BinderCallsStatsService | BinderCallsStatsService.LifeCycle |
Binder call metrics |
| 7 | LooperStatsService | LooperStatsService.Lifecycle |
Handler message timing |
| 8 | RollbackManagerService | RollbackManagerService |
APK rollback management |
| 9 | NativeTombstoneManagerService | NativeTombstoneManagerService |
Native crash tracking |
| 10 | BugreportManagerService | BugreportManagerService |
Bugreport capture |
| 11 | GpuService | GpuService |
GPU driver management |
| 12 | RemoteProvisioningService | RemoteProvisioningService |
Remote key provisioning |
20.3.3 Other Services (Major Subset)¶
The startOtherServices() method is the largest -- it starts the bulk of
the system services. Here is a comprehensive catalog organized by functional
area:
Security and Credentials¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| KeyChainSystemService | KeyChainSystemService |
security/ |
Certificate management |
| KeyAttestationApplicationIdProvider | Direct registration | security/ |
Key attestation IDs |
| LockSettingsService | LockSettingsService.Lifecycle |
locksettings/ |
Screen lock and encryption |
| PersistentDataBlockService | PersistentDataBlockService |
pdb/ |
Factory reset protection |
| OemLockService | OemLockService |
oemlock/ |
Bootloader lock state |
| TrustManagerService | TrustManagerService |
trust/ |
Trust agents (Smart Lock) |
| BiometricService | BiometricService |
biometrics/ |
Biometric coordination |
| AuthService | AuthService |
biometrics/ |
Authentication routing |
| FaceService | FaceService |
biometrics/sensors/face/ |
Face unlock |
| FingerprintService | FingerprintService |
biometrics/sensors/fingerprint/ |
Fingerprint unlock |
| AttestationVerificationService | AttestationVerificationManagerService |
security/ |
Attestation verification |
| AdvancedProtectionService | AdvancedProtectionService.Lifecycle |
security/advancedprotection/ |
Advanced protection mode |
| CredentialManagerService | CredentialManagerService |
credentials/ |
Credential management |
Window, Display, and Input¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| WindowManagerService | WindowManagerService |
wm/ |
Window management and composition |
| InputManagerService | InputManagerService.Lifecycle |
input/ |
Input event routing |
| InputMethodManagerService | InputMethodManagerService.Lifecycle |
inputmethod/ |
Soft keyboard management |
| AccessibilityManagerService | AccessibilityManagerService.Lifecycle |
accessibility/ |
Accessibility features |
| DeviceStateManagerService | DeviceStateManagerService |
devicestate/ |
Foldable/posture states |
| ColorDisplayService | ColorDisplayService |
display/color/ |
Night light, color correction |
| UiModeManagerService | UiModeManagerService |
core | Car/TV/watch mode detection |
Networking¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| NetworkManagementService | NetworkManagementService |
net/ |
Network interface management |
| NetworkPolicyManagerService | NetworkPolicyManagerService |
net/ |
Data usage policies |
| ConnectivityService | Loaded from APEX JAR | connectivity module | Network connectivity |
| VpnManagerService | VpnManagerService |
core | VPN management |
| WiFiService | Loaded from APEX JAR | WiFi module | WiFi management |
| WiFiScanningService | Loaded from APEX JAR | WiFi module | WiFi scanning |
| WiFiAwareService | Loaded from APEX JAR | WiFi module | WiFi Aware (NAN) |
| WiFiP2pService | Loaded from APEX JAR | WiFi module | WiFi Direct |
| BluetoothService | Loaded from APEX JAR | Bluetooth module | Bluetooth management |
| NetworkStatsService | Loaded from APEX JAR | connectivity module | Network statistics |
Storage and Package Management¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| StorageManagerService | StorageManagerService.Lifecycle |
core | Volume and storage management |
| StorageStatsService | StorageStatsService.Lifecycle |
usage/ |
Storage usage statistics |
| DeviceStorageMonitorService | DeviceStorageMonitorService |
storage/ |
Low storage warnings |
| BackupManagerService | BackupManagerService.Lifecycle |
backup/ |
App backup and restore |
| BlobStoreManagerService | BlobStoreManagerService |
blob/ |
Shared binary large objects |
Power and Thermal¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| HintManagerService | HintManagerService |
power/hint/ |
Performance hints to HAL |
| DeviceIdleController | DeviceIdleController |
core | Doze mode management |
| DreamManagerService | DreamManagerService |
dreams/ |
Screen savers and doze UI |
| TwilightService | TwilightService |
twilight/ |
Sunrise/sunset tracking |
Audio, Media, and Camera¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| AudioService | AudioService.Lifecycle |
audio/ |
Audio routing and volume |
| SoundTriggerMiddlewareService | SoundTriggerMiddlewareService.Lifecycle |
soundtrigger_middleware/ |
"Hey Google" detection |
| SoundTriggerService | SoundTriggerService |
soundtrigger/ |
Sound trigger management |
| MediaSessionService | MediaSessionService |
media/ |
Media playback control |
| MediaRouterService | MediaRouterService |
media/ |
Media output routing |
| MediaProjectionManagerService | MediaProjectionManagerService |
media/projection/ |
Screen recording/casting |
| MediaResourceMonitorService | MediaResourceMonitorService |
media/ |
Media resource tracking |
| MediaMetricsManagerService | MediaMetricsManagerService |
media/metrics/ |
Media performance metrics |
| CameraServiceProxy | CameraServiceProxy |
camera/ |
Camera service coordination |
| BroadcastRadioService | BroadcastRadioService |
broadcastradio/ |
AM/FM radio |
Notifications and Status¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| NotificationManagerService | NotificationManagerService |
notification/ |
Notification management |
| StatusBarManagerService | StatusBarManagerService |
statusbar/ |
Status bar control |
Location, Time, and Sensors¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| LocationManagerService | LocationManagerService.Lifecycle |
location/ |
Location providers |
| TimeDetectorService | TimeDetectorService.Lifecycle |
timedetector/ |
Automatic time setting |
| TimeZoneDetectorService | TimeZoneDetectorService.Lifecycle |
timezonedetector/ |
Time zone detection |
| LocationTimeZoneManagerService | LocationTimeZoneManagerService.Lifecycle |
timezonedetector/location/ |
Location-based TZ |
| NetworkTimeUpdateService | NetworkTimeUpdateService |
timedetector/ |
NTP time sync |
| GnssTimeUpdateService | GnssTimeUpdateService.Lifecycle |
timedetector/ |
GPS time sync |
| CountryDetectorService | CountryDetectorService |
core | Country detection |
| AltitudeService | AltitudeService.Lifecycle |
location/altitude/ |
Altitude data |
| SensorNotificationService | SensorNotificationService |
core | Sensor event notifications |
App Management¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| DevicePolicyManagerService | DevicePolicyManagerService.Lifecycle |
devicepolicy/ |
Enterprise device management |
| ShortcutService | ShortcutService.Lifecycle |
pm/ |
App shortcuts |
| LauncherAppsService | LauncherAppsService |
pm/ |
Launcher-app interaction |
| CrossProfileAppsService | CrossProfileAppsService |
pm/ |
Cross-profile app launching |
| AppHibernationService | AppHibernationService |
apphibernation/ |
Unused app hibernation |
| AppBindingService | AppBindingService.Lifecycle |
appbinding/ |
System app binding |
| BackgroundInstallControlService | BackgroundInstallControlService |
pm/ |
Background install control |
| GameManagerService | GameManagerService.Lifecycle |
app/ |
Game mode management |
Communication¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| TelecomLoaderService | TelecomLoaderService |
telecom/ |
Telecom service loading |
| TelephonyRegistry | TelephonyRegistry |
core | Telephony event broadcasting |
| MmsServiceBroker | MmsServiceBroker |
core | MMS service coordination |
| ClipboardService | ClipboardService |
clipboard/ |
System clipboard |
Jobs and Scheduling¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| AlarmManagerService | AlarmManagerService |
alarm/ |
Alarm scheduling |
| JobSchedulerService | JobSchedulerService |
job/ |
Deferred job scheduling |
Content and Search¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| AccountManagerService | AccountManagerService.Lifecycle |
accounts/ |
Account management |
| ContentService | ContentService.Lifecycle |
content/ |
Content provider sync |
| SearchManagerService | SearchManagerService.Lifecycle |
search/ |
System search |
| ContentCaptureManagerService | ContentCaptureManagerService |
contentcapture/ |
Content capture for intelligence |
| AppSearchModule | Loaded from APEX | AppSearch module | On-device search indexing |
TV and HDMI¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| HdmiControlService | HdmiControlService |
hdmi/ |
HDMI-CEC control |
| TvInputManagerService | TvInputManagerService |
tv/ |
TV input framework |
| TvInteractiveAppManagerService | TvInteractiveAppManagerService |
tv/interactive/ |
Interactive TV apps |
| TunerResourceManagerService | TunerResourceManagerService |
tv/tunerresourcemanager/ |
TV tuner resources |
Text and Localization¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| TextServicesManagerService | TextServicesManagerService.Lifecycle |
textservices/ |
Spell checker |
| TextClassificationManagerService | TextClassificationManagerService.Lifecycle |
textclassifier/ |
Smart text selection |
| FontManagerService | FontManagerService.Lifecycle |
graphics/fonts/ |
System font management |
| LocaleManagerService | LocaleManagerService |
locales/ |
Per-app locale |
| GrammaticalInflectionService | GrammaticalInflectionService |
grammaticalinflection/ |
Grammatical gender |
Hardware and Peripherals¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| UsbService | UsbService.Lifecycle |
usb/ |
USB host/device management |
| SerialManagerService | SerialManagerService.Lifecycle |
serial/ |
Serial port management |
| HardwarePropertiesManagerService | HardwarePropertiesManagerService |
core | CPU/GPU temperatures |
| ConsumerIrService | ConsumerIrService |
core | IR blaster |
| VibratorManagerService | VibratorManagerService.Lifecycle |
vibrator/ |
Haptic feedback |
| DockObserver | DockObserver |
core | Dock state detection |
| WiredAccessoryManager | WiredAccessoryManager |
core | Wired headset detection |
| MidiService | MidiService.Lifecycle |
midi/ |
MIDI device management |
AI and Intelligence¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| VoiceInteractionManagerService | VoiceInteractionManagerService |
voiceinteraction/ |
Voice assistant |
| SpeechRecognitionManagerService | SpeechRecognitionManagerService |
speech/ |
Speech recognition |
| AppPredictionManagerService | AppPredictionManagerService |
appprediction/ |
App usage prediction |
| SmartspaceManagerService | SmartspaceManagerService |
smartspace/ |
At-a-glance widgets |
| AttentionManagerService | AttentionManagerService |
attention/ |
User attention detection |
| RotationResolverManagerService | RotationResolverManagerService |
rotationresolver/ |
Rotation based on face |
| AmbientContextManagerService | AmbientContextManagerService |
ambientcontext/ |
Ambient context detection |
| WearableSensingManagerService | WearableSensingManagerService |
wearable/ |
Wearable sensor processing |
| OnDeviceIntelligenceManagerService | Loaded from APEX | On-device intelligence | On-device AI services |
System Infrastructure¶
| Service | Class | Source Package | Purpose |
|---|---|---|---|
| DropBoxManagerService | DropBoxManagerService |
core | Error/diagnostic log storage |
| IncidentCompanionService | IncidentCompanionService |
incident/ |
Incident reporting |
| StatsCompanion | Loaded from APEX | statsd module | Metrics collection helper |
| StatsPullAtomService | StatsPullAtomService |
stats/ |
Pull-based metrics atoms |
| BinaryTransparencyService | BinaryTransparencyService |
core | Binary integrity verification |
| PinnerService | PinnerService |
pinner/ |
Pin critical files in RAM |
| TracingServiceProxy | TracingServiceProxy |
tracing/ |
Perfetto trace coordination |
| LogcatManagerService | LogcatManagerService |
logcat/ |
Logcat access management |
| CoverageService | CoverageService |
coverage/ |
Code coverage (debug builds) |
| GraphicsStatsService | GraphicsStatsService |
graphics | Frame timing statistics |
20.3.4 Mainline Module Services (APEX-delivered)¶
Several services are delivered through mainline module APEXes and loaded from standalone JAR files:
| Module | JAR Path | Service Classes |
|---|---|---|
| WiFi | /apex/com.android.wifi/javalib/service-wifi.jar |
WifiService, WifiScanningService, WifiRttService, WifiAwareService, WifiP2pService |
| Bluetooth | /apex/com.android.bt/javalib/service-bluetooth.jar |
BluetoothService |
| Connectivity | /apex/com.android.tethering/javalib/service-connectivity.jar |
ConnectivityServiceInitializer, NetworkStatsServiceInitializer |
| UWB | /apex/com.android.uwb/javalib/service-uwb.jar |
UwbService |
| Statsd | /apex/com.android.os.statsd/javalib/service-statsd.jar |
StatsCompanion.Lifecycle |
| Scheduling | /apex/com.android.scheduling/javalib/service-scheduling.jar |
RebootReadinessManagerService |
| Profiling | /apex/com.android.profiling/javalib/service-profiling.jar |
ProfilingService.Lifecycle |
| DeviceLock | /apex/com.android.devicelock/javalib/service-devicelock.jar |
DeviceLockService |
20.3.5 Core Server Package Structure¶
The frameworks/base/services/core/java/com/android/server/ directory
contains 102 sub-packages and 74 top-level Java files. Here is the complete
sub-package listing organized by functional domain:
Process and Activity Management¶
am/-- ActivityManagerService, process management, broadcast dispatchwm/-- WindowManagerService, ActivityTaskManagerService, window policyapp/-- GameManagerServiceappbinding/-- AppBindingServiceapphibernation/-- AppHibernationServiceappop/-- AppOpsService (app operation permissions)appwindowlayout/-- AppWindowLayoutSettingsService
Package Management¶
pm/-- PackageManagerService, UserManagerService, Installerintegrity/-- AppIntegrityManagerServicerollback/-- RollbackManagerService
Security¶
biometrics/-- BiometricService, FaceService, FingerprintServicelocksettings/-- LockSettingsServicepermission/-- AccessCheckingService, permission grantssecurity/-- KeyChain, attestation, advanced protectiontrust/-- TrustManagerServicesensorprivacy/-- SensorPrivacyServiceselinux/-- SELinux audit logging
Display and Graphics¶
display/-- DisplayManagerService, ColorDisplayServicegraphics/-- FontManagerServicedreams/-- DreamManagerService
Input and Accessibility¶
input/-- InputManagerServiceinputmethod/-- InputMethodManagerServiceaccessibility/-- AccessibilityManagerService
Networking¶
connectivity/-- PacProxyService, IpConnectivityMetricsnet/-- NetworkManagementService, NetworkPolicyManagerServicevcn/-- VcnManagementService
Power and Thermal¶
power/-- PowerManagerService, ShutdownThread, HintManagerServicepowerstats/-- PowerStatsService
Audio and Media¶
audio/-- AudioServicemedia/-- MediaSessionService, MediaRouterService, MediaProjectionsoundtrigger/-- SoundTriggerServicesoundtrigger_middleware/-- SoundTriggerMiddlewareServicebroadcastradio/-- BroadcastRadioServicecamera/-- CameraServiceProxy
Communication¶
telecom/-- TelecomLoaderServicecompanion/-- CompanionDeviceManagerService
Storage¶
storage/-- DeviceStorageMonitorServiceblob/-- BlobStoreManagerServicepdb/-- PersistentDataBlockService
Time and Location¶
timedetector/-- TimeDetectorService, NetworkTimeUpdateServicetimezonedetector/-- TimeZoneDetectorServicetimezone/-- Time zone data managementlocation/-- LocationManagerServicetwilight/-- TwilightService
Content¶
content/-- ContentServicecontentcapture/-- ContentCaptureManagerServicesearch/-- SearchManagerServiceaccounts/-- AccountManagerService
Notifications and Status Bar¶
notification/-- NotificationManagerServicestatusbar/-- StatusBarManagerServiceslice/-- SliceManagerService
Device Management¶
devicepolicy/-- DevicePolicyManagerServicedevicestate/-- DeviceStateManagerService
System Services¶
flags/-- FeatureFlagsServicecompat/-- PlatformCompatcrashrecovery/-- CrashRecoveryAdaptorcriticalevents/-- CriticalEventLogcpu/-- CpuMonitorServicegpu/-- GpuServiceincident/-- IncidentCompanionServicestats/-- StatsCompaniontracing/-- TracingServiceProxylogcat/-- LogcatManagerServiceos/-- BugreportManagerService, SchedulingPolicyServicerecoverysystem/-- RecoverySystemServiceresources/-- ResourcesManagerServiceuri/-- UriGrantsManagerServiceutils/-- Utility classes
Specialized¶
tv/-- TvInputManagerService, TvRemoteServicehdmi/-- HdmiControlServicevibrator/-- VibratorManagerServicelights/-- LightsServiceusb/-- (module-level, not in core)vr/-- VR mode supportom/-- OverlayManagerServicewallpaper/-- WallpaperManagerServicetheming/-- ThemeManagerServicewebkit/-- WebViewUpdateServicesensors/-- SensorServicepinner/-- PinnerServiceclipboard/-- ClipboardServiceemergency/-- EmergencyAffordanceService
Intelligence and ML¶
attention/-- AttentionManagerServiceambientcontext/-- AmbientContextManagerServicerotationresolver/-- RotationResolverManagerServicespeech/-- SpeechRecognitionManagerServicetextclassifier/-- TextClassificationManagerServicetextservices/-- TextServicesManagerService
Miscellaneous¶
infra/-- Infrastructure base classesfeature/-- Feature detectionfirewall/-- Intent firewallhealth/-- Health HAL integrationlocales/-- LocaleManagerServicegrammaticalinflection/-- GrammaticalInflectionServicememory/-- Memory managementprivatecompute/-- Private compute servicesrole/-- Role management helperssignedconfig/-- Signed configurationtestharness/-- Test harness modeupdates/-- System update handlingwearable/-- WearableSensingManagerService
20.4 Service Start Order¶
20.4.1 startBootstrapServices()¶
The bootstrap phase (line 1176-1451 of SystemServer.java) starts the
services that form the critical dependency chain. The exact order is
significant because of mutual dependencies:
graph TD
subgraph "startBootstrapServices()"
A1["ArtModuleServiceInitializer"] --> A2["Watchdog.start()"]
A2 --> A3["ProtoLog init"]
A3 --> A4["PlatformCompat"]
A4 --> A5["FileIntegrityService"]
A5 --> A6["Installer"]
A6 --> A7["DeviceIdentifiersPolicyService"]
A7 --> A8["FeatureFlagsService"]
A8 --> A9["UriGrantsManagerService"]
A9 --> A10["PowerStatsService"]
A10 --> A11["IStatsService (native)"]
A11 --> A12["MemtrackProxyService (native)"]
A12 --> A13["AccessCheckingService"]
A13 --> A14["ActivityTaskManagerService"]
A14 --> A15["ActivityManagerService"]
A15 --> A16["DataLoaderManagerService"]
A16 --> A17["IncrementalService (native)"]
A17 --> A18["PowerManagerService"]
A18 --> A19["ThermalManagerService"]
A19 --> A20["AMS.initPowerManagement()"]
A20 --> A21["RecoverySystemService"]
A21 --> A22["LightsService"]
A22 --> A23["DisplayManagerService"]
A23 --> A24["PHASE_WAIT_FOR_DEFAULT_DISPLAY (100)"]
A24 --> A25["DomainVerificationService"]
A25 --> A26["PackageManagerService"]
A26 --> A27["UserManagerService"]
A27 --> A28["AMS.setSystemProcess()"]
A28 --> A29["Watchdog.init()"]
A29 --> A30["OverlayManagerService"]
A30 --> A31["ResourcesManagerService"]
A31 --> A32["SensorPrivacyService"]
A32 --> A33["SensorService"]
end
style A14 fill:#fdd,stroke:#333
style A15 fill:#fdd,stroke:#333
style A18 fill:#ffd,stroke:#333
style A23 fill:#ffd,stroke:#333
style A26 fill:#fdd,stroke:#333
style A24 fill:#ddf,stroke:#333
Key dependency relationships in the bootstrap phase:
- Watchdog starts first (line 1192-1196): It must be running before any service that might deadlock.
- Installer before PackageManager (line 1228-1230):
installdmust create critical directories before PMS scans packages. - AMS and ATMS together (line 1274-1283): These two are tightly coupled -- ATMS manages activities/tasks while AMS manages processes.
- PowerManager early (line 1296-1302): Many services need power management.
- DisplayManager before PMS (line 1339-1341): Package manager needs display metrics for density-based resource selection.
- PHASE_WAIT_FOR_DEFAULT_DISPLAY (line 1344-1346): All services needing display information wait here.
- PackageManager pauses Watchdog (line 1364-1370): PMS initialization is so slow that the Watchdog is explicitly paused.
20.4.2 startCoreServices()¶
Core services (line 1457-1533) are simpler -- no circular dependencies:
startCoreServices()
+-- SystemConfigService
+-- BatteryService
+-- UsageStatsService
+-- WebViewUpdateService (if FEATURE_WEBVIEW)
+-- CachedDeviceStateService
+-- BinderCallsStatsService
+-- LooperStatsService
+-- RollbackManagerService
+-- NativeTombstoneManagerService
+-- BugreportManagerService
+-- GpuService
+-- RemoteProvisioningService
+-- CpuMonitorService (debug builds only)
20.4.3 startOtherServices()¶
The startOtherServices() method (line 1539-3600+) is by far the longest.
It contains conditional service starts based on device features, form
factor (phone/watch/TV/auto), and feature flags. The high-level flow:
startOtherServices()
|
+-- Pre-WMS services
| +-- KeyChainSystemService
| +-- BinaryTransparencyService
| +-- SchedulingPolicyService
| +-- TelecomLoaderService
| +-- TelephonyRegistry
| +-- AccountManagerService
| +-- ContentService
| +-- System providers installation
| +-- DropBoxManagerService
| +-- HintManagerService
| +-- RoleManagerService
| +-- VibratorManagerService
| +-- AlarmManagerService
| +-- InputManagerService
| +-- DeviceStateManagerService
| +-- CameraServiceProxy
|
+-- WindowManagerService startup
| +-- PHASE_WAIT_FOR_SENSOR_SERVICE (200)
| +-- WindowManagerService.main()
| +-- AMS.setWindowManager()
| +-- WMS.onInitReady()
| +-- BluetoothService
|
+-- Post-WMS services
| +-- InputMethodManagerService
| +-- AccessibilityManagerService
| +-- StorageManagerService
| +-- UiModeManagerService
| +-- LockSettingsService
| +-- DevicePolicyManagerService
| +-- StatusBarManagerService
| +-- NetworkManagementService
| +-- NetworkPolicyManagerService
| +-- WiFi services (from APEX)
| +-- ConnectivityService (from APEX)
| +-- NotificationManagerService
| +-- LocationManagerService
| +-- AudioService
| +-- JobSchedulerService
| +-- BackupManagerService
| +-- Biometric services
| +-- ShortcutService
| +-- LauncherAppsService
| +-- MediaProjectionManagerService
| +-- SliceManagerService
| +-- StatsCompanion (from APEX)
| +-- AutofillManagerService
| +-- ClipboardService
| +-- TracingServiceProxy
|
+-- Boot phase transitions
| +-- PHASE_LOCK_SETTINGS_READY (480)
| +-- PHASE_SYSTEM_SERVICES_READY (500)
| +-- Device-specific services
| +-- PHASE_DEVICE_SPECIFIC_SERVICES_READY (520)
| +-- SafetyCenterService
| +-- AppSearchModule
| +-- HealthConnectManagerService
|
+-- AMS.systemReady() callback
+-- PHASE_ACTIVITY_MANAGER_READY (550)
+-- CarServiceHelperService (automotive)
+-- Networking systemReady calls
+-- PHASE_THIRD_PARTY_APPS_CAN_START (600)
+-- Start SystemUI
+-- PHASE_BOOT_COMPLETED (1000)
20.4.4 The Boot Phase Sequence in Context¶
Here is how boot phases interleave with service starts. Each vertical position represents a moment in time:
sequenceDiagram
participant SS as SystemServer
participant SSM as SystemServiceManager
participant Services as All Services
Note over SS: startBootstrapServices()
SS->>SSM: Start Watchdog, AMS, PMS, etc.
SSM->>Services: PHASE_WAIT_FOR_DEFAULT_DISPLAY (100)
Note over SS: startCoreServices()
SS->>SSM: Start Battery, Usage, WebView, etc.
Note over SS: startOtherServices()
SSM->>Services: PHASE_WAIT_FOR_SENSOR_SERVICE (200)
SS->>SSM: Start WMS, Bluetooth, Audio, etc.
SS->>SSM: LockSettings.systemReady()
SSM->>Services: PHASE_LOCK_SETTINGS_READY (480)
SSM->>Services: PHASE_SYSTEM_SERVICES_READY (500)
SS->>SSM: Start device-specific services
SSM->>Services: PHASE_DEVICE_SPECIFIC_SERVICES_READY (520)
Note over SS: AMS.systemReady() callback
SSM->>Services: PHASE_ACTIVITY_MANAGER_READY (550)
SS->>SSM: Start network stack, tethering
SSM->>Services: PHASE_THIRD_PARTY_APPS_CAN_START (600)
SS->>SS: Start SystemUI
SSM->>Services: PHASE_BOOT_COMPLETED (1000)
Note over SS: Looper.loop() -- forever
20.4.5 Conditional Service Starts¶
Many services are started only when specific hardware features are present.
SystemServer checks PackageManager.hasSystemFeature() before starting:
| Feature Flag | Services Gated |
|---|---|
FEATURE_BLUETOOTH |
BluetoothService |
FEATURE_WIFI |
WiFi*, WifiScanning |
FEATURE_WIFI_RTT |
WifiRttService |
FEATURE_WIFI_AWARE |
WifiAwareService |
FEATURE_WIFI_DIRECT |
WifiP2pService |
FEATURE_USB_HOST or FEATURE_USB_ACCESSORY |
UsbService |
FEATURE_FINGERPRINT |
FingerprintService |
FEATURE_FACE |
FaceService |
FEATURE_IRIS |
IrisService |
FEATURE_COMPANION_DEVICE_SETUP |
CompanionDeviceManagerService |
FEATURE_HDMI_CEC |
HdmiControlService |
FEATURE_LIVE_TV |
TvInputManagerService, TvInteractiveAppManagerService |
FEATURE_PRINTING |
PrintManagerService |
FEATURE_BACKUP |
BackupManagerService |
FEATURE_APP_WIDGETS |
AppWidgetService |
FEATURE_MIDI |
MidiService |
FEATURE_TELEPHONY |
TelecomLoaderService, MmsServiceBroker |
FEATURE_AUTOFILL |
AutofillManagerService |
FEATURE_CREDENTIALS |
CredentialManagerService |
FEATURE_CONTEXT_HUB |
ContextHubSystemService |
FEATURE_UWB |
UwbService |
FEATURE_CONSUMER_IR |
ConsumerIrService |
FEATURE_BROADCAST_RADIO |
BroadcastRadioService |
FEATURE_PICTURE_IN_PICTURE |
MediaResourceMonitorService |
FEATURE_TUNER |
TunerResourceManagerService |
Form factor checks also gate services:
| Form Factor | Boolean Variable | Example Services Affected |
|---|---|---|
| Watch | isWatch |
Many services skipped (Search, Twilight, etc.) |
| TV | isTv |
TvRemoteService enabled; VibratorManager skipped |
| Automotive | isAutomotive |
CarServiceHelperService enabled |
| ARC (ChromeOS) | isArc |
ArcSystemHealthService, special AudioService |
20.5 Watchdog¶
20.5.1 Purpose and Architecture¶
The Watchdog (defined in Watchdog.java) is a critical safety mechanism that
detects when system_server threads become unresponsive. If a monitored thread
fails to respond within the timeout period (default: 60 seconds), the Watchdog
kills system_server, triggering a runtime restart. This is preferable to
leaving the device in an unresponsive state.
From the class documentation (line 84-86):
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 84
/**
* This class calls its monitor every minute. Killing this process if they
* don't return.
**/
public class Watchdog implements Dumpable {
The Watchdog is a singleton (line 484-490):
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 484
public static Watchdog getInstance() {
if (sWatchdog == null) {
sWatchdog = new Watchdog();
}
return sWatchdog;
}
20.5.2 Default Timeout¶
The default timeout is 60 seconds in production, or 10 seconds in debug builds (line 101):
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 101
private static final long DEFAULT_TIMEOUT = DB ? 10 * 1000 : 60 * 1000;
The pre-watchdog timeout ratio divides the full timeout into check intervals (line 107):
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 107
private static final int PRE_WATCHDOG_TIMEOUT_RATIO = 4;
This means with a 60-second timeout, the Watchdog checks every 15 seconds.
At the 15-second mark it enters WAITED_UNTIL_PRE_WATCHDOG state and
generates a non-fatal thread dump. At 60 seconds, it becomes OVERDUE and
kills the process.
20.5.3 Completion States¶
The Watchdog defines four states (lines 114-117):
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 114
static final int COMPLETED = 0;
static final int WAITING = 1;
static final int WAITED_UNTIL_PRE_WATCHDOG = 2;
static final int OVERDUE = 3;
stateDiagram-v2
[*] --> COMPLETED : Check posted
COMPLETED --> WAITING : Thread busy
WAITING --> WAITED_UNTIL_PRE_WATCHDOG : > timeout/4 elapsed
WAITED_UNTIL_PRE_WATCHDOG --> OVERDUE : > timeout elapsed
OVERDUE --> [*] : Kill system_server
WAITING --> COMPLETED : Check completed
WAITED_UNTIL_PRE_WATCHDOG --> COMPLETED : Check completed
20.5.4 HandlerChecker¶
The core monitoring mechanism is the HandlerChecker inner class (line
263-436). Each HandlerChecker is associated with a Handler (and therefore
a specific thread's Looper):
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 263
public static class HandlerChecker implements Runnable {
private final Handler mHandler;
private final String mName;
private final ArrayList<Monitor> mMonitors = new ArrayList<Monitor>();
private long mWaitMaxMillis;
private boolean mCompleted;
private Monitor mCurrentMonitor;
private long mStartTimeMillis;
private int mPauseCount;
The check mechanism works as follows:
- The Watchdog thread calls
scheduleCheckLocked()which posts theHandlerChecker(as aRunnable) to the front of the monitored thread's message queue. - When the monitored thread processes the message,
run()executes all registered monitors and setsmCompleted = true. - If the monitored thread is blocked (deadlocked, or processing a very
slow message), the
Runnablenever executes, andmCompletedremainsfalse.
The run() method (lines 373-390):
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 373
@Override
public void run() {
final int size = mMonitors.size();
for (int i = 0 ; i < size ; i++) {
synchronized (mLock) {
mCurrentMonitor = mMonitors.get(i);
}
mCurrentMonitor.monitor();
}
synchronized (mLock) {
mCompleted = true;
mCurrentMonitor = null;
}
}
There is an important optimization (line 311-321): if the target looper is currently polling (idle), the HandlerChecker skips posting. An idle looper means the thread is not blocked -- no need to waste time with a context switch.
20.5.5 Monitored Threads¶
The Watchdog constructor (line 492-549) registers checkers for all critical system_server threads:
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 492
private Watchdog() {
mThread = new Thread(this::run, "watchdog");
// Custom monitor checker thread
ServiceThread t = new ServiceThread("watchdog.monitor",
android.os.Process.THREAD_PRIORITY_DEFAULT, true);
t.start();
mMonitorChecker = new HandlerChecker(
new Handler(t.getLooper()), "monitor thread", mLock);
mHandlerCheckers.add(withDefaultTimeout(mMonitorChecker));
// Foreground thread
mHandlerCheckers.add(withDefaultTimeout(
new HandlerChecker(FgThread.getHandler(),
"foreground thread", mLock)));
// Main thread
mHandlerCheckers.add(withDefaultTimeout(
new HandlerChecker(new Handler(Looper.getMainLooper()),
"main thread", mLock)));
// UI thread
mHandlerCheckers.add(withDefaultTimeout(
new HandlerChecker(UiThread.getHandler(),
"ui thread", mLock)));
// I/O thread
mHandlerCheckers.add(withDefaultTimeout(
new HandlerChecker(IoThread.getHandler(),
"i/o thread", mLock)));
// Display thread
mHandlerCheckers.add(withDefaultTimeout(
new HandlerChecker(DisplayThread.getHandler(),
"display thread", mLock)));
// Animation thread
mHandlerCheckers.add(withDefaultTimeout(
new HandlerChecker(AnimationThread.getHandler(),
"animation thread", mLock)));
// Surface animation thread
mHandlerCheckers.add(withDefaultTimeout(
new HandlerChecker(SurfaceAnimationThread.getHandler(),
"surface animation thread", mLock)));
// Binder thread monitor
addMonitor(new BinderThreadMonitor());
mInterestingJavaPids.add(Process.myPid());
}
The eight monitored threads plus the monitor thread total nine checkers.
20.5.6 The Monitor Interface¶
Services that hold critical locks should implement Watchdog.Monitor
(line 460-462):
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 460
public interface Monitor {
void monitor();
}
The monitor() method should attempt to acquire the service's lock and
return. If the lock is held by a deadlocked thread, monitor() will block,
and the Watchdog will detect the deadlock.
The BinderThreadMonitor (line 453-458) checks that at least one Binder
thread is available:
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 453
private static final class BinderThreadMonitor implements Watchdog.Monitor {
@Override
public void monitor() {
Binder.blockUntilThreadAvailable();
}
}
If all 31 Binder threads are blocked (e.g., in a deadlock chain), this monitor will trigger the Watchdog.
20.5.7 The Watchdog Run Loop¶
The main Watchdog loop (line 858-900+) runs continuously:
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 858
private void run() {
boolean preWatchdogTriggered = false;
// ...
while (true) {
// ...
final long watchdogTimeoutMillis = mWatchdogTimeoutMillis;
final long checkIntervalMillis =
watchdogTimeoutMillis / PRE_WATCHDOG_TIMEOUT_RATIO;
synchronized (mLock) {
// Schedule checks on all handler checkers
for (int i=0; i<mHandlerCheckers.size(); i++) {
HandlerCheckerAndTimeout hc = mHandlerCheckers.get(i);
hc.checker().scheduleCheckLocked(
hc.customTimeoutMillis()
.orElse(watchdogTimeoutMillis
* Build.HW_TIMEOUT_MULTIPLIER));
}
// Wait for check interval
long start = SystemClock.uptimeMillis();
while (timeout > 0) {
// ...
mLock.wait(timeout);
// ...
}
// Evaluate results
final int waitState = evaluateCheckerCompletionLocked();
if (waitState == COMPLETED) {
// everything is fine
continue;
} else if (waitState == WAITING) {
continue;
} else if (waitState == WAITED_UNTIL_PRE_WATCHDOG) {
// pre-watchdog: dump but don't kill
}
}
// If OVERDUE: collect stacks and kill
}
}
20.5.8 What Happens When Watchdog Triggers¶
When the Watchdog detects an OVERDUE state:
- Stack trace collection: Dumps stack traces of:
- system_server (Java threads)
- "Interesting" Java processes (StorageManager, phone process)
- Native processes of interest (surfaceflinger, audioserver, cameraserver, mediaserver, etc.)
-
HAL services matching HIDL and AIDL interfaces of interest
-
Dropbox entry: Writes the collected data to DropBoxManager.
-
Process kill: Calls
Process.killProcess(Process.myPid())to terminate system_server. -
Runtime restart: The init process detects that system_server has died and triggers a full runtime restart (all Java processes are killed and respawned from Zygote).
The native processes of interest (line 126-149):
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 126
public static final String[] NATIVE_STACKS_OF_INTEREST = new String[] {
"/system/bin/audioserver",
"/system/bin/cameraserver",
"/system/bin/drmserver",
"/system/bin/keystore2",
"/system/bin/mediaserver",
"/system/bin/netd",
"/system/bin/servicemanager",
"/system/bin/surfaceflinger",
"/system/bin/vold",
"media.extractor",
"media.metrics",
"media.codec",
"media.swcodec",
"media.transcoding",
"com.android.bluetooth",
"/apex/com.android.art/bin/artd",
"/apex/com.android.os.statsd/bin/statsd",
"/apex/com.android.virt/bin/virtualizationservice",
// ...
};
20.5.9 Watchdog Pause Mechanism¶
For known long-running operations, the Watchdog provides pause/resume APIs. For example, PackageManagerService initialization (line 1364-1370 in SystemServer.java):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1364
try {
Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
mPackageManagerService = PackageManagerService.main(
mSystemContext, installer, domainVerificationService,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF);
} finally {
Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
}
Similarly, DEX optimization pauses the Watchdog (line 1972-1978):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1972
try {
Watchdog.getInstance().pauseWatchingCurrentThread("dexopt");
mPackageManagerService.updatePackagesIfNeeded();
} catch (Throwable e) {
reportWtf("update packages", e);
} finally {
Watchdog.getInstance().resumeWatchingCurrentThread("dexopt");
}
The pause mechanism supports nesting -- each pauseLocked() increments
a counter, and each resumeLocked() decrements it. Monitoring only
resumes when the counter reaches zero.
20.5.10 Timeout History and Loop Breaking¶
The Watchdog tracks timeout history to detect crash loops (line 120-123):
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 120
private static final String TIMEOUT_HISTORY_FILE =
"/data/system/watchdog-timeout-history.txt";
private static final String PROP_FATAL_LOOP_COUNT =
"framework_watchdog.fatal_count";
private static final String PROP_FATAL_LOOP_WINDOWS_SECS =
"framework_watchdog.fatal_window.second";
If system_server repeatedly crashes due to Watchdog timeouts within a
configured window, the system can take more drastic recovery action
(such as entering recovery mode).
20.6 Threading Model¶
20.6.1 Overview¶
The system_server process uses a carefully designed threading model with
shared singleton threads for different priority levels. Rather than each
service creating its own thread, most services share a small set of
well-known threads. This reduces context switching, simplifies lock
ordering, and makes the system easier to reason about.
graph TB
subgraph "system_server Threads"
ML["Main Looper<br/>android.main<br/>PRIORITY_FOREGROUND"]
DT["DisplayThread<br/>android.display<br/>PRIORITY_DISPLAY+1"]
AT["AnimationThread<br/>android.anim<br/>PRIORITY_DISPLAY"]
SAT["SurfaceAnimationThread<br/>android.anim.lf<br/>PRIORITY_DISPLAY"]
UT["UiThread<br/>android.ui<br/>PRIORITY_FOREGROUND"]
FT["FgThread<br/>android.fg<br/>PRIORITY_DEFAULT"]
IT["IoThread<br/>android.io<br/>PRIORITY_DEFAULT"]
BT["BackgroundThread<br/>android.bg<br/>PRIORITY_BACKGROUND"]
PT["PermissionThread<br/>android.perm<br/>PRIORITY_DEFAULT"]
BT2["Binder Threads<br/>Binder:PID_N<br/>(up to 31)"]
WD["Watchdog Thread<br/>watchdog"]
end
ML -.->|"Lifecycle callbacks"| DT
DT -.->|"Display updates"| AT
AT -.->|"Animation"| SAT
UT -.->|"System dialogs"| FT
FT -.->|"Foreground ops"| IT
IT -.->|"Disk/Network IO"| BT
style ML fill:#f99,stroke:#333
style DT fill:#f9f,stroke:#333
style AT fill:#f9f,stroke:#333
style BT fill:#9cf,stroke:#333
20.6.2 ServiceThread Base Class¶
All system server threads extend ServiceThread (defined in
frameworks/base/core/java/com/android/server/ServiceThread.java),
which itself extends HandlerThread:
// frameworks/base/core/java/com/android/server/ServiceThread.java, line 30
public class ServiceThread extends HandlerThread {
private final boolean mAllowIo;
public ServiceThread(String name, int priority, boolean allowIo) {
super(name, priority);
mAllowIo = allowIo;
}
@Override
public void run() {
if (!mAllowIo) {
StrictMode.initThreadDefaults(null);
}
super.run();
}
protected static Handler makeSharedHandler(Looper looper) {
return new Handler(looper, null, false, /* shared= */ true);
}
}
The allowIo parameter controls StrictMode enforcement. Threads that should
not perform disk or network I/O (like the display and animation threads)
set this to false, causing StrictMode violations if I/O occurs.
The makeSharedHandler() factory method creates handlers with shared=true,
allowing multiple components to safely post to the same handler without
holding its internal lock.
20.6.3 Thread Catalog¶
Main Looper Thread¶
- Name: the main thread of
system_server - Priority:
THREAD_PRIORITY_FOREGROUND(-2) - Purpose: Runs the main message loop; receives all
SystemServicelifecycle callbacks - Initialized at:
SystemServer.run()line 937
// frameworks/base/services/java/com/android/server/SystemServer.java, line 937
Looper.prepareMainLooper();
The main looper has slow dispatch/delivery thresholds:
- Slow dispatch: 100ms
- Slow delivery: 200ms
DisplayThread¶
- File:
frameworks/base/services/core/java/com/android/server/DisplayThread.java - Thread name:
android.display - Priority:
THREAD_PRIORITY_DISPLAY + 1(-3) - Allow I/O:
false - Trace tag:
TRACE_TAG_SYSTEM_SERVER - Purpose: Operations affecting what is on the display. Used by WindowManager, DisplayManager, and InputManager for quick real-time operations.
From the source comment (line 26-29):
Shared singleton foreground thread for the system. This is a thread for operations that affect what's on the display, which needs to have a minimum of latency. This thread should pretty much only be used by the WindowManager, DisplayManager, and InputManager to perform quick operations in real time.
AnimationThread¶
- File:
frameworks/base/services/core/java/com/android/server/AnimationThread.java - Thread name:
android.anim - Priority:
THREAD_PRIORITY_DISPLAY(-4) - Allow I/O:
false - Trace tag:
TRACE_TAG_WINDOW_MANAGER - Purpose: All legacy window animations, starting windows, and traversals. Has a slightly higher priority than DisplayThread.
SurfaceAnimationThread¶
- File:
frameworks/base/services/core/java/com/android/server/wm/SurfaceAnimationThread.java - Thread name:
android.anim.lf - Priority:
THREAD_PRIORITY_DISPLAY(-4) - Allow I/O:
false - Trace tag:
TRACE_TAG_WINDOW_MANAGER - Purpose: Runs
SurfaceAnimationRunnerwhich does not hold the window manager lock. This separation prevents animation jank when the WM lock is contended.
UiThread¶
- File:
frameworks/base/services/core/java/com/android/server/UiThread.java - Thread name:
android.ui - Priority:
THREAD_PRIORITY_FOREGROUND(-2) - Allow I/O:
false - Thread group:
THREAD_GROUP_TOP_APP(set inrun()) - Purpose: System UI operations. Must not have operations taking more than a few milliseconds to avoid UI jank.
Special behavior (line 42-46):
// frameworks/base/services/core/java/com/android/server/UiThread.java, line 42
@Override
public void run() {
// Make sure UiThread is in the fg stune boost group
Process.setThreadGroup(Process.myTid(), Process.THREAD_GROUP_TOP_APP);
super.run();
}
The UiThread explicitly places itself in the THREAD_GROUP_TOP_APP
scheduling group for maximum CPU priority.
FgThread (Foreground Thread)¶
- File:
frameworks/base/core/java/com/android/server/FgThread.java - Thread name:
android.fg - Priority:
THREAD_PRIORITY_DEFAULT(0) - Allow I/O:
true - Purpose: Foreground service operations that should not be blocked by background work. Many services schedule their primary work here.
From the source comment (line 27-35):
Shared singleton foreground thread for the system. This is a thread for regular foreground service operations, which shouldn't be blocked by anything running in the background. In particular, the shared background thread could be doing relatively long-running operations like saving state to disk (in addition to simply being a background priority), which can cause operations scheduled on it to be delayed for a user-noticeable amount of time.
IoThread¶
- File:
frameworks/base/services/core/java/com/android/server/IoThread.java - Thread name:
android.io - Priority:
THREAD_PRIORITY_DEFAULT(0) - Allow I/O:
true - Purpose: Non-background operations that may briefly block on network I/O (not waiting for data, but communicating with network daemons).
BackgroundThread¶
- File:
frameworks/base/core/java/com/android/internal/os/BackgroundThread.java - Thread name:
android.bg - Priority:
THREAD_PRIORITY_BACKGROUND(10) - Purpose: Background operations across the system. Shares a singleton across the entire process. Has very generous slow thresholds:
- Slow dispatch: 10,000ms (10 seconds!)
- Slow delivery: 30,000ms (30 seconds!)
The generous thresholds reflect that background operations are expected to be slower and are not on the critical path for user experience.
PermissionThread¶
- File:
frameworks/base/services/core/java/com/android/server/PermissionThread.java - Thread name:
android.perm - Priority:
THREAD_PRIORITY_DEFAULT(0) - Allow I/O:
true - Purpose: Handles calls to and from PermissionController, and synchronization between permissions and app-ops states.
20.6.4 Thread Priority Summary¶
| Thread | Name | Priority | Numeric | Allow I/O | StrictMode |
|---|---|---|---|---|---|
| AnimationThread | android.anim |
DISPLAY | -4 | No | Enforced |
| SurfaceAnimationThread | android.anim.lf |
DISPLAY | -4 | No | Enforced |
| DisplayThread | android.display |
DISPLAY+1 | -3 | No | Enforced |
| UiThread | android.ui |
FOREGROUND | -2 | No | Enforced |
| Main Looper | main |
FOREGROUND | -2 | N/A | N/A |
| FgThread | android.fg |
DEFAULT | 0 | Yes | Not enforced |
| IoThread | android.io |
DEFAULT | 0 | Yes | Not enforced |
| PermissionThread | android.perm |
DEFAULT | 0 | Yes | Not enforced |
| BackgroundThread | android.bg |
BACKGROUND | 10 | Yes | Not enforced |
20.6.5 Handler, Looper, and MessageQueue¶
Each shared thread has a Looper running a MessageQueue. Services
interact with threads by posting Message objects or Runnable callbacks
through Handler instances:
graph LR
subgraph "Thread Architecture"
direction TB
S1["Service A"] -->|"handler.post()"| H["Handler"]
S2["Service B"] -->|"handler.sendMessage()"| H
H --> MQ["MessageQueue"]
MQ --> L["Looper.loop()"]
L -->|"dispatch"| Target["Handler.handleMessage()"]
end
Key patterns used in system_server:
- Shared handlers: Created with
shared=trueto allow posting from any thread without external synchronization. - Handler executors:
HandlerExecutorwraps a Handler as a JavaExecutor, allowing use with modern async APIs. - Message priorities:
Message.setAsynchronous(true)bypasses sync barriers, used for time-critical operations.
20.6.6 Binder Threads¶
In addition to the named threads, system_server maintains a pool of
up to 31 Binder threads (line 493 of SystemServer.java):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 493
private static final int sMaxBinderThreads = 31;
Binder threads are named Binder:PID_N where PID is the process ID and
N is the thread number. These threads handle all incoming IPC from app
processes. When all 31 threads are busy, new incoming Binder calls
queue up, and the Watchdog's BinderThreadMonitor will eventually
trigger if the congestion persists.
20.6.7 Thread Selection Guidelines¶
When implementing a system service, choosing the right thread is critical:
| Scenario | Recommended Thread | Rationale |
|---|---|---|
| Display composition, window layout | DisplayThread | Minimal latency for display |
| Window animations | AnimationThread | Highest priority for smooth animation |
| Surface animations (lock-free) | SurfaceAnimationThread | Avoids WM lock contention |
| System dialogs, overlays | UiThread | Foreground priority, TOP_APP group |
| Service business logic | FgThread | Default priority, not blocked by background |
| Disk I/O, database writes | IoThread | Allows I/O, default priority |
| Non-urgent background work | BackgroundThread | Low priority, generous timeouts |
| Permission checks | PermissionThread | Dedicated to avoid blocking other threads |
20.6.8 SystemServerInitThreadPool¶
During boot, system_server uses a temporary thread pool for parallel
initialization (line 944):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 944
SystemServerInitThreadPool.start();
This pool allows multiple independent initialization tasks to run concurrently, reducing boot time. Examples include:
SystemConfig.getInstance()(line 1156)- Secondary Zygote preloading (line 1581)
- Sensor manager service startup (line 1743)
- HIDL services startup (line 1750)
- WebView preparation (line 3363)
The pool is shut down after initialization completes and is not used during normal operation.
20.7 Try It¶
20.7.1 Listing All System Services¶
Use service list to see all registered Binder services:
This produces output like:
Found 290 services:
0 DockObserver: [android.os.IBinder]
1 SurfaceFlinger: [android.ui.ISurfaceComposer]
2 accessibility: [android.view.accessibility.IAccessibilityManager]
3 account: [android.accounts.IAccountManager]
4 activity: [android.app.IActivityManager]
5 activity_task: [android.app.IActivityTaskManager]
...
Count the total:
20.7.2 Inspecting system_server Process¶
View basic process information:
# Process ID
adb shell pidof system_server
# Thread count
adb shell ls /proc/$(adb shell pidof system_server)/task | wc -l
# Process status
adb shell cat /proc/$(adb shell pidof system_server)/status | head -20
# Memory usage
adb shell dumpsys meminfo system_server
20.7.3 Dumpsys Commands¶
dumpsys is the primary tool for inspecting service state. Each service
implements a dump() method:
# Dump all services (very long!)
adb shell dumpsys
# Dump a specific service
adb shell dumpsys activity
adb shell dumpsys window
adb shell dumpsys package
adb shell dumpsys power
adb shell dumpsys notification
adb shell dumpsys audio
adb shell dumpsys connectivity
adb shell dumpsys display
adb shell dumpsys input
adb shell dumpsys alarm
adb shell dumpsys jobscheduler
adb shell dumpsys battery
adb shell dumpsys usagestats
adb shell dumpsys deviceidle
# Dump the SystemServer dumper for internal state
adb shell dumpsys system_server_dumper
adb shell dumpsys system_server_dumper --list
adb shell dumpsys system_server_dumper --name SystemServer
adb shell dumpsys system_server_dumper --name Watchdog
20.7.4 Inspecting Boot Phases¶
Boot phase transitions are logged and can be traced:
# View boot timing events
adb shell logcat -b events | grep boot_progress
# View SystemServer timing tags
adb shell logcat -s SystemServerTiming
# Full boot tracing with Perfetto
adb shell perfetto -o /data/misc/perfetto-traces/boot.pb \
-c - <<EOF
buffers: { size_kb: 65536 }
data_sources: {
config {
name: "android.log"
android_log_config {
log_ids: LID_EVENTS
}
}
}
duration_ms: 60000
EOF
20.7.5 Observing Service Start Order¶
The SystemServer logs each service start with timing information:
# Filter for service start messages
adb shell logcat -s SystemServer SystemServiceManager
# Look for specific boot phase transitions
adb shell logcat | grep -E "PHASE_|startBootPhase"
20.7.6 Watchdog Diagnostics¶
# Dump Watchdog state
adb shell dumpsys system_server_dumper --name Watchdog
# View Watchdog-related logs
adb shell logcat -s Watchdog
# Check for past Watchdog kills
adb shell logcat -b crash | grep -i watchdog
# View timeout history
adb shell cat /data/system/watchdog-timeout-history.txt
20.7.7 Thread Inspection¶
# List all system_server threads with names
adb shell ps -T -p $(adb shell pidof system_server)
# View specific named threads
adb shell ps -T -p $(adb shell pidof system_server) | grep -E \
"android\.(display|anim|ui|fg|io|bg|perm)|Binder:|watchdog"
# Get Java thread dump (sends SIGQUIT)
adb shell kill -3 $(adb shell pidof system_server)
# Then check /data/anr/ for the trace file
adb shell ls -la /data/anr/
20.7.8 Service Dependencies and Boot Timing¶
# View how long each service took to start
adb shell logcat -s SystemServerTimingAsync SystemServerTiming | \
grep -E "traceBegin|traceEnd"
# Check if a specific service is running
adb shell service check activity
adb shell service check window
adb shell service check package
# Call a service directly
adb shell service call activity 1 # IBinder.FIRST_CALL_TRANSACTION
20.7.9 Examining SystemServiceManager State¶
# Dump all registered system services
adb shell dumpsys system_server_dumper --name SystemServiceManager
This shows:
- All registered services and their classes
- Current boot phase
- Service start times
- Active user IDs
20.7.10 Monitoring Binder Thread Pool¶
# Check Binder thread usage
adb shell cat /proc/$(adb shell pidof system_server)/status | \
grep Threads
# View Binder calls stats
adb shell dumpsys binder_calls_stats
# View specific Binder transaction information
adb shell cat /sys/kernel/debug/binder/proc/$(adb shell pidof system_server) \
2>/dev/null | head -50
20.7.11 Forcing a Watchdog Timeout (Development Only)¶
On userdebug/eng builds, you can test the Watchdog by inducing a deadlock. WARNING: This will crash system_server and restart the runtime.
# Reduce watchdog timeout (settings must be available)
adb shell settings put global watchdog_timeout_millis 10000
# Or use the debug property
adb shell setprop persist.sys.debug.watchdog_timeout 10
20.7.12 Tracing Service Startup with Perfetto¶
# Record a boot trace
adb shell setprop persist.debug.atrace.boottrace 1
adb shell setprop persist.traced.enable 1
# After reboot, pull the trace
adb pull /data/misc/perfetto-traces/boottrace.perfetto-trace
# Open in ui.perfetto.dev
The trace will show all the TimingsTraceAndSlog spans from SystemServer,
including every service start and boot phase transition, with precise
timestamps.
20.7.13 Simulating Boot Phases¶
You can watch boot phases progress in real time during a reboot:
# Reboot and immediately start capturing
adb reboot && sleep 5 && adb wait-for-device && \
adb logcat -s SystemServiceManager | grep -i phase
Expected output sequence:
SystemServiceManager: Starting phase 100
SystemServiceManager: Starting phase 200
SystemServiceManager: Starting phase 480
SystemServiceManager: Starting phase 500
SystemServiceManager: Starting phase 520
SystemServiceManager: Starting phase 550
SystemServiceManager: Starting phase 600
SystemServiceManager: Starting phase 1000
20.7.14 Examining Service Registration¶
To see how a specific service is registered:
# Check if a service exists and get its interface descriptor
adb shell service check activity
adb shell service check window
adb shell service check package
# Get service debug info (PID, interface)
adb shell dumpsys -l
20.7.15 Monitoring Looper Statistics¶
# Dump looper statistics to see message processing times
adb shell dumpsys looper_stats
# This shows for each looper:
# - Message count
# - Total time
# - Max time
# - Exception count
This data comes from the LooperStatsService started in
startCoreServices() and is invaluable for identifying which messages
are slow on which threads.
20.8 Deep Dive: Key Service Internals¶
20.8.1 ActivityManagerService and ActivityTaskManagerService¶
The ActivityManagerService (AMS) and ActivityTaskManagerService (ATMS) are
the most important services in system_server. They were originally a
single monolithic service, but were split to separate process management
(AMS) from activity/task management (ATMS).
Source files:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.javaframeworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
The startup sequence in startBootstrapServices() (lines 1274-1283):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1274
t.traceBegin("StartActivityManager");
ActivityTaskManagerService atm = mSystemServiceManager.startService(
ActivityTaskManagerService.Lifecycle.class).getService();
mActivityManagerService = ActivityManagerService.Lifecycle.startService(
mSystemServiceManager, atm);
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
mWindowManagerGlobalLock = atm.getGlobalLock();
Key observations:
- ATMS starts first and returns its service reference.
- AMS starts second and receives the ATMS reference.
- AMS gets references to SystemServiceManager and Installer.
- The WindowManagerGlobalLock is obtained from ATMS.
AMS responsibilities:
- Process lifecycle management (start, stop, kill)
- OOM adjustment calculation
- Broadcast dispatch
- Content provider management
- Crash and ANR handling
- App permissions enforcement at runtime
ATMS responsibilities:
- Activity stack and task management
- Activity lifecycle (create, resume, pause, stop, destroy)
- Recent tasks
- Multi-window management
- Activity transitions
Later in startBootstrapServices(), critical cross-references are
established (lines 1406-1418):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1406
t.traceBegin("SetSystemProcess");
mActivityManagerService.setSystemProcess();
t.traceEnd();
// ...
t.traceBegin("InitWatchdog");
watchdog.init(mSystemContext, mActivityManagerService);
t.traceEnd();
AMS.setSystemProcess() registers the activity service as a Binder
service and sets up the system process's ApplicationInfo. The Watchdog
initialization requires AMS for registering the reboot broadcast
receiver.
20.8.2 WindowManagerService¶
WindowManagerService (WMS) manages all windows on the device -- app windows, status bar, navigation bar, dialogs, toasts, and more. It is one of the most complex services in Android.
Source: frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
WMS starts in startOtherServices() (lines 1722-1730):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1722
t.traceBegin("StartWindowManagerService");
mSystemServiceManager.startBootPhase(t,
SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);
wm = WindowManagerService.main(context, inputManager, !mFirstBoot,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
| DUMP_FLAG_PROTO);
WMS depends on:
- InputManagerService (for input event dispatch)
- PhoneWindowManager (for policy decisions like key handling)
- ActivityTaskManagerService (for activity window management)
- SensorService (must wait for PHASE_WAIT_FOR_SENSOR_SERVICE)
The WMS is registered with DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
because its dump output is essential for debugging display issues.
After WMS starts, several critical callbacks fire:
// line 1733
mActivityManagerService.setWindowManager(wm);
// line 1737
wm.onInitReady();
// line 1758
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
inputManager.start();
// line 1763
mDisplayManagerService.windowManagerAndInputReady();
This dance of cross-references is why WMS, AMS, InputManager, and DisplayManager are all in the bootstrap/early-other phase -- they cannot function independently.
20.8.3 PackageManagerService¶
PackageManagerService (PMS) manages all installed packages (APKs), their permissions, components, and metadata. It is so large and complex that its initialization is one of the longest operations during boot.
Source: frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
PMS starts in startBootstrapServices() (lines 1362-1374):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1362
t.traceBegin("StartPackageManagerService");
try {
Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
mPackageManagerService = PackageManagerService.main(
mSystemContext, installer, domainVerificationService,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF);
} finally {
Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
}
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
PMS depends on:
- Installer (
installddaemon interface) - DomainVerificationService (app link verification)
- DisplayManager (must have display metrics for resource selection)
The Watchdog is explicitly paused during PMS initialization because the
package scan can take many seconds (or even minutes on first boot with
many pre-installed apps). Without the pause, the Watchdog would kill
system_server during a legitimate long operation.
20.8.4 PowerManagerService¶
PowerManagerService manages the device's power state -- wake locks, display power, doze mode, battery saver, and shutdown.
Source: frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1300
t.traceBegin("StartPowerManager");
mPowerManagerService = mSystemServiceManager.startService(
PowerManagerService.class);
t.traceEnd();
PowerManager starts early because many other services need to acquire wake locks during initialization. After AMS starts, power management is fully initialized:
// line 1310
t.traceBegin("InitPowerManagement");
mActivityManagerService.initPowerManagement();
t.traceEnd();
20.8.5 NotificationManagerService¶
NotificationManagerService (NMS) manages all notifications, channels, notification policies, and interactions with the status bar.
Source: frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
// frameworks/base/services/java/com/android/server/SystemServer.java, line 2341
t.traceBegin("StartNotificationManager");
mSystemServiceManager.startService(NotificationManagerService.class);
SystemNotificationChannels.removeDeprecated(context);
SystemNotificationChannels.createAll(context);
notification = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
NMS depends on StorageManagerService (for media/USB notifications), which is why StorageManager starts first when the filesystem is available.
20.8.6 DisplayManagerService¶
DisplayManagerService manages physical and virtual displays, display power state, and display adapters.
Source: frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1339
t.traceBegin("StartDisplayManager");
mDisplayManagerService = mSystemServiceManager.startService(
DisplayManagerService.class);
The critical PHASE_WAIT_FOR_DEFAULT_DISPLAY (100) boot phase follows immediately:
// line 1344
t.traceBegin("WaitForDisplay");
mSystemServiceManager.startBootPhase(t,
SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
No package scanning can begin until the default display is available, because PackageManagerService needs display metrics to select the correct resources for the device's density.
20.9 Service Communication Patterns¶
20.9.1 Binder Services vs. Local Services¶
Services in system_server communicate through two distinct patterns:
Binder services are registered with ServiceManager and are accessible
from any process on the device. They provide the public API surface that
apps use:
graph LR
subgraph "App Process"
A["Activity"] -->|"getSystemService()"| SM["ServiceManager<br/>Proxy"]
end
subgraph "system_server"
SM -->|"Binder IPC"| SVC["SystemService<br/>Binder Stub"]
end
Local services are registered with LocalServices and are accessible
only within the system_server process. They provide privileged internal
APIs that other system services use:
graph LR
subgraph "system_server"
SVC1["Service A"] -->|"LocalServices.getService()"| SVC2["Service B<br/>Internal API"]
end
The dual-interface pattern is extremely common. For example, PowerManager:
- Binder:
IPowerManager-- for apps to acquire wake locks - Local:
PowerManagerInternal-- for system services to force display on/off, override wake lock behavior, etc.
20.9.2 The Lifecycle Inner Class Pattern¶
Many services use an inner Lifecycle class that extends SystemService:
public class ExampleManagerService extends IExampleManager.Stub {
public static final class Lifecycle extends SystemService {
private ExampleManagerService mService;
public Lifecycle(Context context) {
super(context);
}
@Override
public void onStart() {
mService = new ExampleManagerService(getContext());
publishBinderService(Context.EXAMPLE_SERVICE, mService);
publishLocalService(ExampleManagerInternal.class,
mService.new LocalService());
}
@Override
public void onBootPhase(int phase) {
mService.onBootPhase(phase);
}
}
}
This pattern separates the Binder stub implementation (the outer class)
from the lifecycle management (the inner class). The Lifecycle class
is what SystemServiceManager instantiates and manages.
20.9.3 Service Dependencies¶
Service dependencies in system_server are not formally declared (unlike
dependency injection frameworks). Instead, they are implicit in the
start order. A service that needs PowerManager is simply started after
PowerManagerService. This works because SystemServer.java explicitly
controls the order.
There have been multiple attempts to formalize dependencies:
- The
TODO: Use service dependencies insteadcomment appears inSystemServer.java(line 1762) - The
dependenciesparameter inSystemServiceconstructor was added for the Ravenwood testing environment - Boot phases provide coarse-grained synchronization
However, for the most part, the start order in SystemServer.java remains
the primary dependency mechanism.
20.9.4 Cross-Service Communication via Handlers¶
When one service needs to notify another asynchronously, it posts a message to the target service's handler. For example, when DisplayManagerService detects a display change, it may notify WindowManagerService by posting to the DisplayThread handler.
Common patterns:
- Direct handler posting:
displayThread.getHandler().post(callback) - Message objects:
handler.obtainMessage(MSG_TYPE).sendToTarget() - Local service callbacks: Register a listener interface with
LocalServices.getService()and call it directly
20.9.5 The SystemServer Dumper¶
SystemServer registers a special system_server_dumper Binder service
(line 974) that acts as a central dump coordinator:
// frameworks/base/services/java/com/android/server/SystemServer.java, line 974
ServiceManager.addService("system_server_dumper", mDumper);
mDumper.addDumpable(this);
The SystemServerDumper (lines 759-834) accepts Dumpable objects and
provides a unified interface for dumping their state:
# List all dumpables
adb shell dumpsys system_server_dumper --list
# Dump a specific dumpable
adb shell dumpsys system_server_dumper --name SystemServiceManager
This is separate from the per-service dumpsys mechanism because it
dumps internal system_server state that is not associated with any
specific Binder service.
20.10 Error Handling and Recovery¶
20.10.1 The reportWtf Pattern¶
Throughout SystemServer.java, failed service starts are caught with
a consistent pattern (line 1095-1098):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1095
private void reportWtf(String msg, Throwable e) {
Slog.w(TAG, "***********************************************");
Slog.wtf(TAG, "BOOT FAILURE " + msg, e);
}
Slog.wtf() (What a Terrible Failure) logs the error and, on userdebug
builds, can trigger additional diagnostic actions. Most service start
failures are caught and reported with reportWtf() rather than crashing
system_server, because a partial system is better than no system at all.
20.10.2 Early WTF Handling¶
Before AMS is fully initialized, WTFs cannot be immediately processed
(there is no dropbox yet). SystemServer buffers them (lines 1015-1016):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1016
RuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf);
Later, after AMS is ready, pending WTFs are flushed (lines 3174-3179):
// line 3174
synchronized (SystemService.class) {
if (sPendingWtfs != null) {
mActivityManagerService.schedulePendingSystemServerWtfs(sPendingWtfs);
sPendingWtfs = null;
}
}
20.10.3 Pending Shutdown Check¶
Before starting services, SystemServer checks if a shutdown was pending
from a previous session (lines 1100-1150):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1100
private void performPendingShutdown() {
final String shutdownAction = SystemProperties.get(
ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
if (shutdownAction != null && shutdownAction.length() > 0) {
boolean reboot = (shutdownAction.charAt(0) == '1');
// ...
ShutdownThread.rebootOrShutdown(null, reboot, reason);
}
}
This handles the case where the device was in the middle of a reboot (e.g., for an OTA update) when it crashed. The pending reboot is completed before normal boot continues.
20.10.4 Safe Mode¶
Safe mode is detected after WindowManagerService starts (line 1851):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1851
final boolean safeMode = wm.detectSafeMode();
if (safeMode) {
Settings.Global.putInt(context.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 1);
}
In safe mode:
- Airplane mode is enabled immediately
- AMS enters safe mode (
mActivityManagerService.enterSafeMode()) - Third-party services may be restricted
- The system shows a safe mode overlay
20.10.5 FD Leak Detection¶
On debug builds, SystemServer spawns a thread to monitor file descriptor
usage (line 642-695):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 642
private static void spawnFdLeakCheckThread() {
final int enableThreshold = SystemProperties.getInt(
SYSPROP_FDTRACK_ENABLE_THRESHOLD, 1600);
final int abortThreshold = SystemProperties.getInt(
SYSPROP_FDTRACK_ABORT_THRESHOLD, 3000);
The thread periodically checks the highest file descriptor number:
- Above 1600: Enables
libfdtrackfor detailed tracking - Above 3000: Dumps an hprof heap dump and aborts the process
This prevents a slow FD leak from eventually causing mysterious failures when the process runs out of file descriptors.
20.10.6 CriticalEventLog¶
After all services start, a critical event is logged (line 1038):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1038
CriticalEventLog.getInstance().logSystemServerStarted();
The CriticalEventLog maintains a persistent record of critical system
events (boots, crashes, Watchdog kills) that survives reboots. This data
is used by rescue party logic to detect crash loops and take corrective
action (such as entering recovery mode or disabling problematic apps).
20.11 Performance Considerations¶
20.11.1 Boot Time Optimization¶
SystemServer uses several strategies to minimize boot time:
1. Parallel initialization: The SystemServerInitThreadPool runs
independent init tasks concurrently:
// line 944
SystemServerInitThreadPool.start();
// line 1156 - SystemConfig loading
SystemServerInitThreadPool.submit(SystemConfig::getInstance, ...);
// line 1581 - Secondary Zygote preload
mZygotePreload = SystemServerInitThreadPool.submit(() -> { ... });
// line 1743 - Sensor manager
SystemServerInitThreadPool.submit(() -> {
startISensorManagerService();
});
// line 1750 - HIDL services
SystemServerInitThreadPool.submit(() -> {
startHidlServices();
});
2. Deferred initialization: Many services do minimal work in
onStart() and defer heavy initialization to later boot phases.
3. Lazy loading: Services like FgThread, IoThread, and
BackgroundThread use holder pattern or NoPreloadHolder pattern
for lazy initialization.
4. Boot time tracking: Timing information is tracked and reported:
// line 1049
if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
final long uptimeMillis = SystemClock.elapsedRealtime();
// ...
final long maxUptimeMillis = 60 * 1000;
if (uptimeMillis > maxUptimeMillis) {
Slog.wtf(SYSTEM_SERVER_TIMING_TAG,
"SystemServer init took too long. uptimeMillis=" + uptimeMillis);
}
}
A WTF is logged if boot takes longer than 60 seconds.
20.11.2 Memory Optimization¶
Early in run(), system_server clears its growth limit (line 911):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 911
VMRuntime.getRuntime().clearGrowthLimit();
Normal apps have a heap growth limit (typically 256MB or 512MB), but
system_server removes this limit because it needs to manage the entire
system's state, which can require significant memory.
20.11.3 Binder Performance¶
Several optimizations ensure Binder IPC performance:
Background scheduling disabled (line 929):
This ensures all incoming Binder calls to system_server run at
foreground priority, preventing starvation.
Blocking call warnings (line 880):
Within system_server, blocking (synchronous) Binder calls to other
processes are discouraged because they can cause deadlocks. This setting
logs warnings when they occur.
Transaction callback (line 1062-1067):
// line 1062
Binder.setTransactionCallback(new IBinderCallback() {
@Override
public void onTransactionError(int pid, int code, int flags, int err) {
mActivityManagerService.frozenBinderTransactionDetected(
pid, code, flags, err);
}
});
This detects when a frozen (cached) process receives a Binder transaction that fails, which is important for managing process lifecycle.
20.11.4 Slow Log Thresholds¶
Each thread has configurable slow dispatch and delivery thresholds:
| Thread | Dispatch Threshold | Delivery Threshold |
|---|---|---|
| Main Looper | 100ms | 200ms |
| UiThread | 100ms | 200ms |
| FgThread | 100ms | 200ms |
| PermissionThread | 100ms | 200ms |
| BackgroundThread | 10,000ms | 30,000ms |
| DisplayThread | Default | Default |
| AnimationThread | Default | Default |
| IoThread | Default | Default |
When a message exceeds these thresholds, a warning is logged with the message details and timing information. This is invaluable for identifying jank-causing operations.
The definitions:
- Dispatch threshold: How long it takes to start processing a message after it is dequeued
- Delivery threshold: How long between when a message is posted and when processing begins (includes time waiting in the queue)
20.12 APEX Module Service Loading¶
20.12.1 The Modularization Challenge¶
As Android modularized via Project Mainline, services that were previously
compiled into services.jar needed to be loaded from module-delivered
APEXes. This created a challenge: how to load a SystemService subclass
from a JAR that is not on the default classpath.
20.12.2 SystemServerClassLoaderFactory¶
The SystemServiceManager.startServiceFromJar() method creates a
PathClassLoader for each standalone JAR:
// frameworks/base/services/core/java/com/android/server/SystemServiceManager.java, line 167
public SystemService startServiceFromJar(String className, String path) {
PathClassLoader pathClassLoader =
SystemServerClassLoaderFactory.getOrCreateClassLoader(
path, this.getClass().getClassLoader(),
isJarInTestApex(path));
final Class<SystemService> serviceClass =
loadClassFromLoader(className, pathClassLoader);
return startService(serviceClass);
}
The class loader hierarchy:
- The APEX JAR's
PathClassLoaderhas the system server's default class loader as its parent. - This allows the APEX service to access all framework classes while having its own classes loaded from the APEX JAR.
SystemServerClassLoaderFactorycaches class loaders so the same APEX JAR is not loaded multiple times.
20.12.3 Service Lifecycle with Modules¶
APEX-delivered services participate in the same lifecycle as built-in services. They receive boot phase callbacks, user lifecycle events, and are monitored by the Watchdog. The only difference is the loading mechanism.
Example from WiFi:
// frameworks/base/services/java/com/android/server/SystemServer.java, line 2205
t.traceBegin("StartWifi");
mSystemServiceManager.startServiceFromJar(
WIFI_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH);
Where:
// line 434
private static final String WIFI_APEX_SERVICE_JAR_PATH =
"/apex/com.android.wifi/javalib/service-wifi.jar";
private static final String WIFI_SERVICE_CLASS =
"com.android.server.wifi.WifiService";
20.12.4 Complete APEX JAR Paths¶
Here is the complete mapping of APEX paths used in SystemServer.java:
| Constant | Path |
|---|---|
WIFI_APEX_SERVICE_JAR_PATH |
/apex/com.android.wifi/javalib/service-wifi.jar |
BLUETOOTH_APEX_SERVICE_JAR_PATH |
/apex/com.android.bt/javalib/service-bluetooth.jar |
CONNECTIVITY_SERVICE_APEX_PATH |
/apex/com.android.tethering/javalib/service-connectivity.jar |
UWB_APEX_SERVICE_JAR_PATH |
/apex/com.android.uwb/javalib/service-uwb.jar |
RANGING_APEX_SERVICE_JAR_PATH |
/apex/com.android.uwb/javalib/service-ranging.jar |
STATS_COMPANION_APEX_PATH |
/apex/com.android.os.statsd/javalib/service-statsd.jar |
SCHEDULING_APEX_PATH |
/apex/com.android.scheduling/javalib/service-scheduling.jar |
DEVICE_LOCK_APEX_PATH |
/apex/com.android.devicelock/javalib/service-devicelock.jar |
PROFILING_SERVICE_JAR_PATH |
/apex/com.android.profiling/javalib/service-profiling.jar |
UPROBESTATS_SERVICE_JAR_PATH |
/apex/com.android.uprobestats/javalib/service-uprobestats.jar |
20.13 Device-Specific and Form-Factor Services¶
20.13.1 Device-Specific Services¶
After the standard services start, SystemServer loads OEM-specific
services from a resource array (lines 3232-3244):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 3232
t.traceBegin("StartDeviceSpecificServices");
final String[] classes = mSystemContext.getResources().getStringArray(
R.array.config_deviceSpecificSystemServices);
for (final String className : classes) {
t.traceBegin("StartDeviceSpecificServices " + className);
try {
mSystemServiceManager.startService(className);
} catch (Throwable e) {
reportWtf("starting " + className, e);
}
t.traceEnd();
}
OEMs populate config_deviceSpecificSystemServices in their device
overlays to add custom system services without modifying
SystemServer.java.
20.13.2 Watch-Specific Services¶
Wear OS devices start several additional services:
| Service | Class Reference |
|---|---|
| WearPowerService | WEAR_POWER_SERVICE_CLASS |
| HealthService | HEALTH_SERVICE_CLASS |
| SystemStateDisplayService | SYSTEM_STATE_DISPLAY_SERVICE_CLASS |
| WearConnectivityService | WEAR_CONNECTIVITY_SERVICE_CLASS |
| WearDisplayService | WEAR_DISPLAY_SERVICE_CLASS |
| WearDebugService | WEAR_DEBUG_SERVICE_CLASS (debug builds) |
| WearTimeService | WEAR_TIME_SERVICE_CLASS |
| WearSettingsService | WEAR_SETTINGS_SERVICE_CLASS |
| WearModeService | WEAR_MODE_SERVICE_CLASS |
| WristOrientationService | WRIST_ORIENTATION_SERVICE_CLASS (conditional) |
| WearGestureService | WEAR_GESTURE_SERVICE_CLASS (conditional) |
| WearInputService | WEAR_INPUT_SERVICE_CLASS (conditional) |
| DisplayOffloadService | WEAR_DISPLAYOFFLOAD_SERVICE_CLASS |
These are defined in the com.android.clockwork package and loaded from
the PRODUCT_SYSTEM_SERVER_JARS classpath.
20.13.3 Automotive-Specific Services¶
Automotive (Android Automotive OS) devices start:
// line 3374
t.traceBegin("StartCarServiceHelperService");
final SystemService cshs = mSystemServiceManager
.startService(CAR_SERVICE_HELPER_SERVICE_CLASS);
The CarServiceHelperService bridges the system server to the Car
Service, which runs in a separate process and manages automotive-specific
features like vehicle HAL, cabin controls, and driving safety.
20.13.4 TV-Specific Services¶
TV devices get additional media services:
| Feature Check | Service |
|---|---|
FEATURE_LIVE_TV or isTv |
TvInteractiveAppManagerService |
FEATURE_LIVE_TV or isTv |
TvInputManagerService |
FEATURE_TUNER |
TunerResourceManagerService |
isTv |
TvRemoteService |
isTv and mediaQualityFw() |
MediaQualityService |
20.13.5 IoT Services¶
Embedded/IoT devices running Android Things:
// line 2941
if (RoSystemFeatures.hasFeatureEmbedded(context)) {
t.traceBegin("StartIoTSystemService");
mSystemServiceManager.startService(IOT_SERVICE_CLASS);
t.traceEnd();
}
20.14 SystemUI Launch¶
20.14.1 The Final Step¶
After all services are running and all boot phases have completed, the very last step before entering the main loop is launching SystemUI (lines 3594-3599):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 3594
t.traceBegin("StartSystemUI");
try {
startSystemUi(context, windowManagerF);
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
SystemUI is a separate app process (not a service within system_server),
but it is started by system_server because it provides the status bar,
navigation bar, notification shade, quick settings, and other critical
UI elements.
20.14.2 The Boot Completed Phase¶
After SystemUI starts, the final boot phase is dispatched:
This signals to all services that the boot is complete. Services can now:
- Allow full user interaction
- Start background maintenance tasks
- Begin collecting statistics
- Enable features that depend on the complete system
20.14.3 The Infinite Loop¶
Finally, the main thread enters the event loop (line 1081):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1081
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
The RuntimeException on line 1082 is a safety net -- Looper.loop()
should never return. If it does, something is catastrophically wrong.
From this point forward, all work in system_server happens through:
- Handler messages on the main looper and shared threads
- Binder thread callbacks from app processes
- Native callbacks from HAL services
- Timer and alarm callbacks
graph TB
subgraph "system_server steady state"
ML["Main Looper<br/>Lifecycle callbacks<br/>Handler messages"]
BT["Binder Threads (x31)<br/>App IPC requests"]
ST["Shared Threads<br/>Display, Anim, UI, Fg, Io, Bg"]
WD["Watchdog<br/>Health monitoring"]
NC["Native Callbacks<br/>HAL, Sensor, Input"]
ML --> |"dispatch to"| ST
BT --> |"enqueue to"| ML
BT --> |"enqueue to"| ST
NC --> |"notify"| ST
WD --> |"monitor all"| ML
WD --> |"monitor all"| ST
WD --> |"monitor"| BT
end
20.15 Debugging system_server¶
20.15.1 Common Failure Modes¶
| Symptom | Likely Cause | Diagnosis |
|---|---|---|
| Device stuck at boot animation | Service init deadlock or crash loop | Check logcat for BOOT FAILURE, Watchdog logs |
| Runtime restart loop | Persistent Watchdog timeout | Check /data/system/watchdog-timeout-history.txt |
| Service not responding (ANR-like) | Lock contention or blocked thread | Get thread dump with kill -3 |
| Binder transaction failures | Thread pool exhaustion | Check dumpsys binder_calls_stats |
| Memory pressure | Heap too large or leak | Check dumpsys meminfo system_server |
| System UI crash | SystemUI process died | Check logcat for SystemUI crashes |
20.15.2 Getting Thread Dumps¶
Java thread dumps are the most useful diagnostic tool for system_server
issues:
# Method 1: SIGQUIT (generates ANR trace)
adb shell kill -3 $(adb shell pidof system_server)
sleep 2
adb pull /data/anr/traces.txt
# Method 2: debuggerd (native + Java stacks)
adb shell debuggerd $(adb shell pidof system_server)
The trace file contains:
- Stack traces for every Java thread
- Lock ownership information
- Thread states (RUNNABLE, BLOCKED, WAITING, etc.)
- Monitor information (which thread holds which lock)
20.15.3 Identifying Deadlocks¶
A classic system_server deadlock involves two services holding locks
and waiting for each other. The thread dump will show:
"android.display" prio=5 tid=12 BLOCKED
- waiting to lock <0x12345678> (a WindowManagerGlobalLock)
held by thread 15
at WindowManagerService.doSomething()
"Binder:1234_5" prio=5 tid=15 BLOCKED
- waiting to lock <0x87654321> (a ActivityManagerService)
held by thread 12
at ActivityManagerService.doSomethingElse()
This shows thread 12 waiting for a lock held by thread 15, while thread 15 waits for a lock held by thread 12 -- a classic deadlock.
20.15.4 Analyzing Boot Timing¶
To identify which service is slowing down boot:
# Get timing for each service start
adb logcat -s SystemServerTiming | sort -t= -k2 -n -r | head -20
20.15.5 Reading Watchdog Dumps¶
When the Watchdog triggers, it writes detailed information to both logcat and DropBox:
# Check DropBox for Watchdog entries
adb shell dumpsys dropbox --print | grep -A 100 "SYSTEM_SERVER_WATCHDOG"
# Check kernel log for the kill
adb shell dmesg | grep system_server
The Watchdog dump includes:
- Which checker(s) were blocked
- Whether blocked in a handler or a specific monitor
- Stack traces of all interesting processes
- Kernel stack traces for native processes
20.15.6 Profiling system_server¶
For performance analysis:
# CPU profiling with simpleperf
adb shell simpleperf record -p $(adb shell pidof system_server) \
--duration 10 -o /data/local/tmp/perf.data
adb pull /data/local/tmp/perf.data
simpleperf report -i perf.data
# Java method tracing (debug builds)
adb shell am profile start system $(adb shell pidof system_server) \
/data/local/tmp/system_server.trace
sleep 5
adb shell am profile stop system
adb pull /data/local/tmp/system_server.trace
20.15.7 Useful System Properties¶
| Property | Purpose | Default |
|---|---|---|
sys.system_server.start_count |
Number of system_server starts since boot | 1 |
sys.system_server.start_elapsed |
Start time (elapsed realtime ms) | varies |
sys.system_server.start_uptime |
Start time (uptime ms) | varies |
persist.sys.debug.fdtrack_enable_threshold |
FD count to enable tracking | 1600 |
persist.sys.debug.fdtrack_abort_threshold |
FD count to abort | 3000 |
persist.sys.debug.fdtrack_interval |
FD check interval (seconds) | 120 |
framework_watchdog.fatal_count |
Watchdog crash count for loop detection | varies |
framework_watchdog.fatal_window.second |
Time window for crash loop detection | varies |
20.16 Writing a Custom System Service¶
20.16.1 Service Structure Template¶
A well-structured system service follows this pattern:
// IMyService.aidl -- define the Binder interface
// MyManagerService.java
package com.android.server.myservice;
public class MyManagerService extends IMyService.Stub {
// Internal interface for other system services
final class LocalService extends MyManagerInternal {
// Privileged operations
}
// Lifecycle class for SystemServiceManager
public static final class Lifecycle extends SystemService {
private MyManagerService mService;
public Lifecycle(Context context) {
super(context);
}
@Override
public void onStart() {
mService = new MyManagerService(getContext());
publishBinderService(Context.MY_SERVICE, mService);
publishLocalService(MyManagerInternal.class,
mService.new LocalService());
}
@Override
public void onBootPhase(int phase) {
if (phase == PHASE_SYSTEM_SERVICES_READY) {
mService.systemReady();
}
}
@Override
public void onUserStarting(@NonNull TargetUser user) {
mService.onUserStarting(user.getUserIdentifier());
}
}
}
20.16.2 Registration in SystemServer¶
Add the service start to the appropriate method in SystemServer.java:
// In startOtherServices() or startCoreServices()
t.traceBegin("StartMyService");
mSystemServiceManager.startService(MyManagerService.Lifecycle.class);
t.traceEnd();
20.16.3 Thread Safety Considerations¶
When writing a system service, thread safety is paramount:
- Binder calls come on Binder threads -- any public method in the Binder stub can be called concurrently from multiple threads.
- Lifecycle callbacks come on the main thread -- but other calls may come simultaneously on Binder threads.
- Use the appropriate shared thread -- do not create new threads for every operation.
- Implement Watchdog.Monitor if you hold a lock that could deadlock with other system services.
- Avoid holding locks during Binder calls to other services -- this is the primary cause of deadlocks.
20.16.4 Testing with Ravenwood¶
The Ravenwood framework supports deviceless testing of system services.
The dependencies parameter in the SystemService constructor helps
Ravenwood understand which other services need to be available:
public MyManagerService(Context context) {
super(context, List.of(PowerManager.class, PackageManager.class));
}
This tells Ravenwood that MyManagerService requires PowerManager
and PackageManager to function, so they must be set up in the test
environment.
20.17 The startApexServices() Phase¶
20.17.1 APEX Service Discovery¶
After startOtherServices() completes, SystemServer enters the fourth
and final startup method: startApexServices(). This phase handles
services that are defined in APEX modules and registered via
SystemServiceRegistry rather than being hardcoded in SystemServer.java.
The key difference from startServiceFromJar() calls in
startOtherServices() is that APEX services discovered here are
declared by the APEX manifest and registered dynamically. This allows
APEX modules to add system services without modifying SystemServer.java
at all.
20.17.2 Updating the Watchdog Timeout¶
After all services are started, the Watchdog timeout is updated from system settings (line 1037):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1037
updateWatchdogTimeout(t);
This call registers a SettingsObserver that watches for changes to
Settings.Global.WATCHDOG_TIMEOUT_MILLIS, allowing the timeout to be
adjusted dynamically by the server-side configuration system:
// frameworks/base/services/core/java/com/android/server/Watchdog.java, line 617
void updateWatchdogTimeout(long timeoutMillis) {
if (!DB && !Build.IS_USERDEBUG
&& timeoutMillis
<= ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS) {
timeoutMillis =
ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS + 1;
}
mWatchdogTimeoutMillis = timeoutMillis;
Slog.i(TAG, "Watchdog timeout updated to "
+ mWatchdogTimeoutMillis + " millis");
}
The timeout cannot be set below the Zygote wrapped PID timeout on non-debug builds to prevent false positives when debugging wrapped applications.
20.18 Lock Ordering and Deadlock Prevention¶
20.18.1 The Lock Hierarchy¶
Within system_server, multiple services hold multiple locks. To prevent
deadlocks, the framework uses an informal lock ordering convention:
- WindowManagerGlobalLock -- The "big lock" shared between WMS and ATMS. This is the most contended lock in the system.
- ActivityManagerService lock -- Protects AMS internal state.
- PowerManagerService.mLock -- Protects power state.
- Individual service locks -- Each service's internal state.
The general rule: always acquire locks in a consistent order. Never hold a service-specific lock while calling into another service that might try to acquire a higher-level lock.
20.18.2 LockGuard¶
The LockGuard class (in frameworks/base/services/core/java/com/android/server/LockGuard.java)
provides runtime lock-order verification:
// Usage pattern:
LockGuard.installLock(this, LockGuard.INDEX_WINDOW);
// Later:
LockGuard.guard(LockGuard.INDEX_POWER); // warns if holding WINDOW lock
When a thread acquires locks out of order, LockGuard logs a warning that helps developers identify potential deadlock scenarios before they become actual deadlocks in the field.
20.18.3 ThreadPriorityBooster¶
The ThreadPriorityBooster class (in
frameworks/base/services/core/java/com/android/server/ThreadPriorityBooster.java)
temporarily boosts thread priority while holding critical locks. This
prevents priority inversion, where a low-priority thread holds a lock
that a high-priority thread needs.
Pattern:
class MyService {
private final ThreadPriorityBooster mBooster =
new ThreadPriorityBooster(
Process.THREAD_PRIORITY_DISPLAY,
LockGuard.INDEX_WINDOW);
void criticalOperation() {
mBooster.boost();
try {
synchronized (mLock) {
// Critical work at display priority
}
} finally {
mBooster.reset();
}
}
}
20.18.4 Common Deadlock Patterns¶
The most common deadlock patterns in system_server:
Pattern 1: Service A calls Service B while holding lock
Thread 1: ServiceA.lock() -> ServiceB.method() -> ServiceB.lock()
Thread 2: ServiceB.lock() -> ServiceA.method() -> ServiceA.lock()
Prevention: Never call into another service while holding your own lock. Instead, copy needed data under lock, release the lock, then make the external call.
Pattern 2: Binder call while holding lock
Thread 1 (Binder): ServiceA.lock() -> app process Binder call
App process: ServiceA.method() -> ServiceA.lock() (blocked!)
Prevention: This is why Binder.setWarnOnBlocking(true) is set in
system_server. Avoid making outgoing Binder calls while holding locks.
Pattern 3: Lock and Handler
Thread 1: lock() -> handler.post(runnable that needs lock)
Handler thread: runnable runs -> tries to acquire lock -> blocked
Meanwhile Thread 1 waits for handler.runWithScissors() -> deadlock
Prevention: Avoid runWithScissors() (post and wait) patterns. Use
asynchronous message passing instead.
20.19 Memory Architecture¶
20.19.1 Heap Configuration¶
system_server has special heap configuration compared to regular apps:
// frameworks/base/services/java/com/android/server/SystemServer.java, line 911
VMRuntime.getRuntime().clearGrowthLimit();
Regular apps typically have:
- Default heap size: 256MB (varies by device)
- Growth limit: same as default (enforced)
system_server:
- Growth limit: removed (unlimited growth)
- Actual usage: typically 200-500MB depending on number of apps installed and device configuration
20.19.2 Shared Memory Optimization¶
Early in run(), system_server initializes a shared memory region
(lines 1021-1022):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1021
ApplicationSharedMemory instance = ApplicationSharedMemory.create();
ApplicationSharedMemory.setInstance(instance);
This shared memory region allows efficient data sharing between
system_server and app processes without Binder IPC overhead. It is
used for high-frequency, small-data communication paths.
20.19.3 Zygote Memory Inheritance¶
Since system_server is forked from Zygote, it inherits:
- All preloaded framework classes (already in the class table)
- Common resources and assets
- ICU and timezone data
- OpenGL/Vulkan driver state
This shared memory (via Linux copy-on-write pages) means the actual
private memory footprint of system_server is much smaller than its
virtual memory size would suggest.
20.19.4 GC Considerations¶
system_server's garbage collector behavior has special implications:
- Large heap: More objects to scan, longer GC pauses
- Concurrent GC: The ART runtime uses concurrent GC to minimize
pause times, but
system_serverallocates rapidly during boot - GC during PMS init: PackageManagerService allocates heavily during package scanning. The ArtModuleServiceInitializer is loaded early (before PMS) specifically to avoid the class linker competing with GC (as noted in the code comment at line 1182-1186):
// line 1180
// This needs to happen before DexUseManagerLocal init. We do it
// here to avoid colliding with a GC. ArtModuleServiceInitializer
// is a class from a separate dex file "service-art.jar", so
// referencing it involves the class linker. The class linker and
// the GC are mutually exclusive (b/263486535).
20.20 The SystemServerInitThreadPool¶
20.20.1 Purpose¶
The SystemServerInitThreadPool provides a temporary thread pool
specifically for parallelizing initialization work during boot. It is
started early (line 944) and shut down after initialization completes.
Source: frameworks/base/services/core/java/com/android/server/SystemServerInitThreadPool.java
20.20.2 Usage Pattern¶
Tasks are submitted as lambdas with descriptive names:
// SystemConfig loading - line 1156
SystemServerInitThreadPool.submit(
SystemConfig::getInstance, "ReadingSystemConfig");
// Secondary Zygote preload - line 1581
mZygotePreload = SystemServerInitThreadPool.submit(() -> {
String[] abis32 = Build.SUPPORTED_32_BIT_ABIS;
if (abis32.length > 0
&& !Process.ZYGOTE_PROCESS.preloadDefault(abis32[0])) {
Slog.e(TAG, "Unable to preload default resources");
}
}, "SecondaryZygotePreload");
// Native sensor manager - line 1743
SystemServerInitThreadPool.submit(() -> {
startISensorManagerService();
}, "StartISensorManagerService");
// HIDL services - line 1750
SystemServerInitThreadPool.submit(() -> {
startHidlServices();
}, "StartHidlServices");
// WebView preparation - line 3363
webviewPrep = SystemServerInitThreadPool.submit(() -> {
ConcurrentUtils.waitForFutureNoInterrupt(
mZygotePreload, "Zygote preload");
mZygotePreload = null;
mWebViewUpdateService.prepareWebViewInSystemServer();
}, "WebViewFactoryPreparation");
20.20.3 Synchronization¶
Some tasks depend on earlier tasks. The Future<?> returned by
submit() allows later code to wait for completion:
// Wait for Zygote preload before WebView prep
ConcurrentUtils.waitForFutureNoInterrupt(mZygotePreload, "Zygote preload");
// Wait for WebView prep before starting third-party apps
if (webviewPrep != null) {
ConcurrentUtils.waitForFutureNoInterrupt(
webviewPrep, WEBVIEW_PREPARATION);
}
20.20.4 Dumping State¶
The pool is registered as a dumpable (line 945):
This allows monitoring which initialization tasks are still pending or have completed during boot.
20.21 Binder Transaction Monitoring¶
20.21.1 Transaction Callbacks¶
After all services start, system_server installs a Binder transaction
callback (lines 1062-1067):
// frameworks/base/services/java/com/android/server/SystemServer.java, line 1062
Binder.setTransactionCallback(new IBinderCallback() {
@Override
public void onTransactionError(int pid, int code, int flags, int err) {
mActivityManagerService.frozenBinderTransactionDetected(
pid, code, flags, err);
}
});
This detects failed Binder transactions to frozen (cached) processes. When a process is frozen (moved to the cgroup freezer), Binder transactions to it fail immediately. This callback notifies AMS, which can then handle the situation (e.g., killing the frozen process or requeuing the transaction).
20.21.2 Post-GC Memory Metrics¶
system_server also registers a post-GC callback for memory monitoring
(lines 1071-1078):
// line 1071
if (android.app.Flags.reportPostgcMemoryMetrics()
&& com.android.libcore.readonly.Flags.postCleanupApis()) {
VMRuntime.addPostCleanupCallback(new Runnable() {
@Override public void run() {
MetricsLoggerWrapper.logPostGcMemorySnapshot();
}
});
}
This collects memory metrics after each GC cycle, providing insights
into the long-term memory behavior of system_server.
20.22 Feature Flags in system_server¶
20.22.1 Flag-Gated Service Starts¶
Many service starts in modern AOSP are gated by feature flags. This allows services to be enabled/disabled without code changes:
// Example: IntrusionDetectionService
if (!isWatch && !isTv && !isAutomotive
&& android.security.Flags.aflApi()) {
t.traceBegin("StartIntrusionDetectionService");
mSystemServiceManager.startService(IntrusionDetectionService.class);
t.traceEnd();
}
// Example: AdvancedProtectionService
if (!isWatch && !isTv && !isAutomotive
&& android.security.Flags.aapmApi()) {
t.traceBegin("StartAdvancedProtectionService");
mSystemServiceManager.startService(
AdvancedProtectionService.Lifecycle.class);
t.traceEnd();
}
// Example: TradeInModeService
if (!isWatch && !isTv && !isAutomotive && enableTradeInMode()) {
t.traceBegin("StartTradeInModeService");
mSystemServiceManager.startService(TradeInModeService.class);
t.traceEnd();
}
// Example: UserRecoveryManagerService
if (enableUserRecoveryManager()) {
t.traceBegin("StartUserRecoveryManager");
mSystemServiceManager.startService(
UserRecoveryManagerService.class);
t.traceEnd();
}
20.22.2 FeatureFlagsService¶
The FeatureFlagsService is started in the bootstrap phase (line 1240):
// line 1240
t.traceBegin("StartFeatureFlagsService");
mSystemServiceManager.startService(FeatureFlagsService.class);
t.traceEnd();
This service is started early because other services need to read flag values during their initialization. It provides the mechanism for distributing runtime flag overrides and keeping processes in sync with the latest flag values.
20.22.3 Crash Recovery Flags¶
The crash recovery mechanism is itself flag-gated (line 1319):
// line 1319
if (!Flags.refactorCrashrecovery()) {
CrashRecoveryAdaptor.rescuePartyRegisterHealthObserver(mSystemContext);
}
And later (line 3208):
// line 3208
if (Flags.refactorCrashrecovery()) {
t.traceBegin("StartCrashRecoveryModule");
CrashRecoveryAdaptor.initializeCrashrecoveryModuleService(
mSystemServiceManager);
t.traceEnd();
} else {
CrashRecoveryAdaptor.packageWatchdogNoteBoot(mSystemContext);
}
This shows the ongoing migration of crash recovery logic from the platform to a modular implementation.
20.23 Architecture Diagrams¶
20.23.1 Complete system_server Architecture¶
graph TB
ZYG["Zygote"] -->|"fork()"| MT
APPS["App Processes"] -->|"Binder IPC"| BTP
subgraph SS["system_server process"]
MT["Main Thread"] --> SSM
BTP["Binder Thread Pool"] --> SSM
WDT["Watchdog Thread"] -->|"monitors"| MT
SSM["SystemServiceManager (orchestrator)"] --> BS
SSM --> CS
subgraph BS["Bootstrap Services"]
AMS["ActivityManagerService"]
PMS["PackageManagerService"]
end
subgraph CS["Core + Other Services"]
WMS["WindowManagerService"]
NMS["NotificationManagerService"]
MORE["+ 100 more..."]
end
end
style SSM fill:#ffd,stroke:#333
style WDT fill:#f99,stroke:#333
style AMS fill:#9df,stroke:#333
style WMS fill:#9df,stroke:#333
style PMS fill:#9df,stroke:#333
20.23.2 Boot Sequence Timeline¶
gantt
title system_server Boot Sequence
dateFormat X
axisFormat %s
section Init
Load native libs :a1, 0, 2
Create system context :a2, 2, 4
Create SSM :a3, 4, 5
section Bootstrap
Watchdog :b1, 5, 6
AMS + ATMS :b2, 6, 10
PowerManager :b3, 10, 12
DisplayManager :b4, 12, 14
PHASE 100 :milestone, 14, 14
PackageManager :b5, 14, 25
UserManager :b6, 25, 27
section Core
BatteryService :c1, 27, 28
UsageStats :c2, 28, 29
WebView :c3, 29, 30
section Other
WMS + InputManager :d1, 30, 35
Bluetooth :d2, 35, 37
Audio :d3, 37, 39
Notification :d4, 39, 41
PHASE 480 :milestone, 41, 41
PHASE 500 :milestone, 42, 42
Device-specific :d5, 42, 45
PHASE 520 :milestone, 45, 45
PHASE 550 :milestone, 46, 46
Network stack :d6, 46, 48
PHASE 600 :milestone, 48, 48
SystemUI :d7, 48, 50
PHASE 1000 :milestone, 50, 50
20.23.3 Service Registration Flow¶
sequenceDiagram
participant SS as SystemServer
participant SSM as SystemServiceManager
participant SVC as MyService.Lifecycle
participant SM as ServiceManager
participant LS as LocalServices
SS->>SSM: startService(MyService.Lifecycle.class)
SSM->>SVC: new Lifecycle(context)
SSM->>SVC: onStart()
SVC->>SM: publishBinderService("my_service", binderStub)
SVC->>LS: publishLocalService(MyInternal.class, localImpl)
SSM->>SSM: mServices.add(lifecycle)
Note over SSM: Later, during boot phase...
SSM->>SVC: onBootPhase(500)
Note over SSM: Later, when user starts...
SSM->>SVC: onUserStarting(user)
20.24 Historical Context¶
20.24.1 Evolution of system_server¶
The system_server architecture has evolved significantly:
Early Android (1.x-2.x):
- Monolithic
SystemServer.javawith inline service construction - No
SystemServicebase class - No boot phases
- Limited threading model
Android 4.x-5.x:
- Introduction of
SystemServicebase class - Boot phases added for orderly initialization
SystemServiceManagerfor lifecycle management- Shared threads introduced (Display, Animation, UI, Fg, Io, Bg)
Android 8.x-9.x (Project Treble):
- HAL interfaces moved to HIDL
- Stronger separation between framework and vendor code
- Watchdog AIDL interface monitoring added
Android 10+ (Project Mainline):
- Services moved to APEX modules
startServiceFromJar()mechanism addedSystemServerClassLoaderFactoryfor APEX class loading- Connectivity, WiFi, Bluetooth services modularized
Android 12+:
- ActivityTaskManagerService split from ActivityManagerService
- PermissionThread added
- Enhanced Watchdog with pre-watchdog timeout
- Feature flag gating of service starts
Android 14+:
- Ravenwood testing framework integration
- Service dependencies for testing
- Enhanced crash recovery module
- Refactored CrashRecovery as a module
20.24.2 The Monolith Pattern¶
system_server follows a "monolithic process, modular services" pattern.
All services run in a single process for several reasons:
- Performance: Intra-process calls via
LocalServicesavoid Binder IPC overhead. Given that services call each other thousands of times per second, this is significant. - Atomicity: Having all services in one process means a crash in any service restarts all of them, maintaining consistency.
- Lock sharing: Critical locks (like
WindowManagerGlobalLock) can be shared across services without IPC. - Memory efficiency: Shared heap reduces overall memory usage.
The downside is that one poorly-written service can bring down the entire system, which is why the Watchdog is so important.
20.24.3 Why Not Microservices?¶
Android considered splitting system services into separate processes (a microservices-like architecture) but rejected it because:
- IPC cost: Every cross-service call would require Binder IPC (~10us minimum), which is unacceptable for the tight interaction patterns between AMS, WMS, and InputManager.
- Consistency: Partial failures would require complex recovery logic. With a monolithic process, it is all-or-nothing.
- Memory overhead: Each process has its own heap, class loading, and VM overhead. Hundreds of small processes would use much more memory than one large process.
The APEX module approach is a middle ground: the code is modular and updatable, but it all runs in the same process.
20.25 Quick Reference¶
20.25.1 Source File Index¶
| File Path | Lines | Purpose |
|---|---|---|
frameworks/base/services/java/com/android/server/SystemServer.java |
~3600 | Entry point, startup orchestration |
frameworks/base/services/core/java/com/android/server/SystemService.java |
641 | Service base class, boot phase constants |
frameworks/base/services/core/java/com/android/server/SystemServiceManager.java |
~500 | Service lifecycle management |
frameworks/base/services/core/java/com/android/server/Watchdog.java |
~1100 | Deadlock detection, thread monitoring |
frameworks/base/core/java/com/android/server/ServiceThread.java |
52 | Handler thread base class |
frameworks/base/services/core/java/com/android/server/DisplayThread.java |
79 | Display operations thread |
frameworks/base/services/core/java/com/android/server/AnimationThread.java |
76 | Window animation thread |
frameworks/base/services/core/java/com/android/server/wm/SurfaceAnimationThread.java |
76 | Lock-free surface animation |
frameworks/base/services/core/java/com/android/server/UiThread.java |
89 | System UI thread |
frameworks/base/core/java/com/android/server/FgThread.java |
69 | Foreground operations thread |
frameworks/base/services/core/java/com/android/server/IoThread.java |
59 | I/O operations thread |
frameworks/base/core/java/com/android/internal/os/BackgroundThread.java |
104 | Background operations thread |
frameworks/base/services/core/java/com/android/server/PermissionThread.java |
72 | Permission operations thread |
frameworks/base/services/core/java/com/android/server/SystemServerInitThreadPool.java |
~100 | Boot-time parallel init pool |
20.25.2 Boot Phase Quick Reference¶
| Value | Constant | Gate |
|---|---|---|
| 100 | PHASE_WAIT_FOR_DEFAULT_DISPLAY |
Default display available |
| 200 | PHASE_WAIT_FOR_SENSOR_SERVICE |
Sensor HAL ready |
| 480 | PHASE_LOCK_SETTINGS_READY |
Lock settings readable |
| 500 | PHASE_SYSTEM_SERVICES_READY |
Core services callable |
| 520 | PHASE_DEVICE_SPECIFIC_SERVICES_READY |
OEM services callable |
| 550 | PHASE_ACTIVITY_MANAGER_READY |
Can broadcast Intents |
| 600 | PHASE_THIRD_PARTY_APPS_CAN_START |
Apps can make Binder calls |
| 1000 | PHASE_BOOT_COMPLETED |
Home app started |
20.25.3 Thread Quick Reference¶
| Thread Name | Java Class | Priority | I/O | Monitored by Watchdog |
|---|---|---|---|---|
main |
Main Looper | FOREGROUND (-2) | Yes | Yes |
android.display |
DisplayThread |
DISPLAY+1 (-3) | No | Yes |
android.anim |
AnimationThread |
DISPLAY (-4) | No | Yes |
android.anim.lf |
SurfaceAnimationThread |
DISPLAY (-4) | No | Yes |
android.ui |
UiThread |
FOREGROUND (-2) | No | Yes |
android.fg |
FgThread |
DEFAULT (0) | Yes | Yes |
android.io |
IoThread |
DEFAULT (0) | Yes | Yes |
android.bg |
BackgroundThread |
BACKGROUND (10) | Yes | No |
android.perm |
PermissionThread |
DEFAULT (0) | Yes | No |
watchdog |
Watchdog |
DEFAULT (0) | N/A | N/A |
watchdog.monitor |
ServiceThread |
DEFAULT (0) | Yes | N/A |
Binder:PID_N |
Binder pool | FOREGROUND (-2) | Yes | Yes (via BinderThreadMonitor) |
20.25.4 Key Constants¶
| Constant | Value | Location |
|---|---|---|
sMaxBinderThreads |
31 | SystemServer.java:493 |
DEFAULT_TIMEOUT |
60,000ms | Watchdog.java:101 |
PRE_WATCHDOG_TIMEOUT_RATIO |
4 | Watchdog.java:107 |
SLOW_DISPATCH_THRESHOLD_MS |
100ms | SystemServer.java:346 |
SLOW_DELIVERY_THRESHOLD_MS |
200ms | SystemServer.java:347 |
DEFAULT_SYSTEM_THEME |
Theme_DeviceDefault_System |
SystemServer.java:499 |
SERVICE_CALL_WARN_TIME_MS |
50ms | SystemServiceManager.java:78 |
DEFAULT_MAX_USER_POOL_THREADS |
3 | SystemServiceManager.java:92 |
USER_POOL_SHUTDOWN_TIMEOUT_SECONDS |
30s | SystemServiceManager.java:97 |
20.25.5 Essential dumpsys Commands¶
| Command | Information Shown |
|---|---|
dumpsys activity |
AMS state: processes, activities, broadcasts |
dumpsys activity processes |
Running processes and OOM adj |
dumpsys window |
WMS state: windows, displays, input |
dumpsys package <pkg> |
Package details, permissions, components |
dumpsys power |
Power state, wake locks, battery stats |
dumpsys notification |
Active notifications and channels |
dumpsys audio |
Audio routing, volumes, devices |
dumpsys connectivity |
Network state, connections |
dumpsys display |
Display configuration, brightness |
dumpsys input |
Input devices, event dispatching |
dumpsys alarm |
Scheduled alarms |
dumpsys jobscheduler |
Pending and running jobs |
dumpsys battery |
Battery state and history |
dumpsys usagestats |
App usage statistics |
dumpsys meminfo system_server |
Memory breakdown |
dumpsys binder_calls_stats |
Binder call statistics |
dumpsys looper_stats |
Handler message timing |
dumpsys system_server_dumper |
Internal system_server state |
service list |
All registered Binder services |
20.26 BackupManagerService¶
The Android backup framework enables applications to back up their data to
cloud or local storage and restore it after device reset, migration, or app
reinstallation. BackupManagerService (BMS) is the system service that
orchestrates this entire process -- managing backup transports, scheduling
key-value and full-data backups, and coordinating restore operations.
Key source files:
| File | Description |
|---|---|
frameworks/base/services/backup/java/com/android/server/backup/BackupManagerService.java |
Top-level delegator service |
frameworks/base/services/backup/java/com/android/server/backup/UserBackupManagerService.java |
Per-user backup logic |
frameworks/base/services/backup/java/com/android/server/backup/TransportManager.java |
Transport lifecycle management |
frameworks/base/services/backup/java/com/android/server/backup/FullBackupJob.java |
JobScheduler integration for full backups |
frameworks/base/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java |
Key-value backup execution |
frameworks/base/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java |
Full backup execution |
frameworks/base/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java |
Restore execution |
frameworks/base/services/backup/java/com/android/server/backup/transport/TransportConnection.java |
Transport binding logic |
20.26.1 Architecture Overview¶
BMS uses a two-layer architecture: a system-level delegator and per-user managers. This design mirrors Android's multi-user model.
graph TB
subgraph "System Level"
BMS["BackupManagerService<br/>IBackupManager.Stub"]
HANDLER["Handler Thread<br/>(backup)"]
end
subgraph "Per-User State"
UBMS0["UserBackupManagerService<br/>(User 0)"]
UBMS10["UserBackupManagerService<br/>(User 10)"]
end
subgraph "Transport Layer"
TM["TransportManager"]
CLOUD["Cloud Transport<br/>(Google backup)"]
LOCAL["Local Transport<br/>(adb backup)"]
end
subgraph "Scheduling"
KVJOB["KeyValueBackupJob<br/>(JobScheduler)"]
FBJOB["FullBackupJob<br/>(JobScheduler)"]
end
subgraph "Execution"
KVTASK["KeyValueBackupTask"]
FBTASK["PerformFullTransportBackupTask"]
RESTORE["PerformUnifiedRestoreTask"]
end
BMS --> HANDLER
BMS -->|"routes by userId"| UBMS0
BMS -->|"routes by userId"| UBMS10
UBMS0 --> TM
TM --> CLOUD
TM --> LOCAL
KVJOB --> UBMS0
FBJOB --> UBMS0
UBMS0 --> KVTASK
UBMS0 --> FBTASK
UBMS0 --> RESTORE
The BackupManagerService class documentation states its role:
// frameworks/base/services/backup/java/com/android/server/backup/BackupManagerService.java
/**
* This class is responsible for handling user-aware operations and acts as
* a delegator, routing incoming calls to the appropriate per-user
* {@link UserBackupManagerService} to handle the corresponding
* backup/restore operation.
*/
public class BackupManagerService extends IBackupManager.Stub
implements BackupManagerInternal {
Each UserBackupManagerService instance maintains its own:
- TransportManager -- tracks registered transports for that user
- BackupHandler -- message-based task scheduling
- ProcessedPackagesJournal -- persistent log of backed-up packages
- DataChangedJournal -- list of packages with pending key-value changes
- FullBackupQueue -- round-robin schedule for full backups
20.26.2 Activation and Disablement¶
BMS can be disabled at two levels:
- Permanent -- The system property
ro.backup.disableset totrue - Temporary -- The
setBackupServiceActive(userId, boolean)API, typically called byDevicePolicyManagerfor enterprise devices
Activation state is tracked using sentinel files:
// frameworks/base/services/backup/java/com/android/server/backup/BackupManagerService.java
private static final String BACKUP_SUPPRESS_FILENAME = "backup-suppress";
private static final String BACKUP_ACTIVATED_FILENAME = "backup-activated";
private static final String REMEMBER_ACTIVATED_FILENAME = "backup-remember-activated";
The activation check follows a four-level precedence:
- Global suppression -- Suppress file for
USER_SYSTEMdisables all users - User-specific suppression -- Suppress file for a particular user
- Default activation -- Whether the user's backup defaults to active
- Explicit activation file -- Presence of activation file for the user
20.26.3 Backup Transports¶
A backup transport is a pluggable component that defines where backup data
goes. Transports are discovered via PackageManager by scanning for services
with the action android.backup.TRANSPORT_HOST:
// frameworks/base/services/backup/java/com/android/server/backup/TransportManager.java
public static final String SERVICE_ACTION_TRANSPORT_HOST =
"android.backup.TRANSPORT_HOST";
The TransportManager maintains a whitelist of allowed transports from
SystemConfig.getBackupTransportWhitelist(). Only whitelisted transports
can register. Each transport is wrapped in a TransportConnection that
handles the Binder binding lifecycle:
sequenceDiagram
participant UBMS as UserBackupManagerService
participant TM as TransportManager
participant TC as TransportConnection
participant BT as BackupTransport (remote service)
UBMS->>TM: getCurrentTransport()
TM->>TC: connect("backup-task")
TC->>BT: bindService()
BT-->>TC: onServiceConnected()
TC-->>TM: BackupTransportClient
TM-->>UBMS: transport ready
Note over UBMS,BT: Backup operations proceed
UBMS->>TC: done
TC->>BT: unbindService()
Google's cloud backup transport (com.google.android.gms/.backup.BackupTransportService)
implements the IBackupTransport interface, but the architecture is open --
OEMs can provide their own transport implementations.
20.26.4 Key-Value vs. Full Backup¶
Android supports two fundamentally different backup strategies:
Key-Value Backup:
- Apps extend
BackupAgentand implementonBackup()/onRestore() - Data is stored as key-value pairs using
BackupDataOutput - Incremental -- only changed keys are transmitted
- Scheduled via
KeyValueBackupJobthroughJobScheduler - Tracked through
DataChangedJournal-- when an app callsBackupManager.dataChanged(), its package name is written to the journal
Full Backup:
- Automatic backup of entire app directories (internal storage, databases, etc.)
- No app code changes required (unless
BackupAgentoverridesonFullBackup()) - Configured via
android:fullBackupContentin the manifest - Scheduled via
FullBackupJobin a round-robin queue - Requires the device to be idle and charging (except on Wear devices)
// frameworks/base/services/backup/java/com/android/server/backup/FullBackupJob.java
builder.setRequiredNetworkType(constants.getFullBackupRequiredNetworkType())
.setRequiresCharging(constants.getFullBackupRequireCharging());
if (!ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
builder.setRequiresDeviceIdle(true);
}
The backup lifecycle for both types:
flowchart TB
subgraph "Key-Value Backup"
KV1["App calls<br/>BackupManager.dataChanged()"]
KV2["Package added to<br/>DataChangedJournal"]
KV3["KeyValueBackupJob fires"]
KV4["KeyValueBackupTask<br/>binds to app's BackupAgent"]
KV5["Agent.onBackup() called<br/>(incremental state delta)"]
KV6["Delta sent to transport<br/>via performBackup()"]
KV1 --> KV2 --> KV3 --> KV4 --> KV5 --> KV6
end
subgraph "Full Backup"
FB1["FullBackupJob fires<br/>(idle + charging)"]
FB2["Next app in<br/>round-robin queue"]
FB3["Bind to app's<br/>BackupAgent"]
FB4["Agent.onFullBackup() called<br/>(or default file walker)"]
FB5["Tar-format stream sent<br/>to transport"]
FB1 --> FB2 --> FB3 --> FB4 --> FB5
end
20.26.5 The BackupHandler Message Protocol¶
UserBackupManagerService uses a handler-based message protocol defined in
BackupHandler:
| Message | Purpose |
|---|---|
MSG_RUN_BACKUP |
Execute a pending key-value backup pass |
MSG_RUN_ADB_BACKUP |
Execute an adb backup (user-initiated) |
MSG_RUN_ADB_RESTORE |
Execute an adb restore |
MSG_RUN_RESTORE |
Execute a cloud restore |
MSG_RUN_CLEAR |
Clear backup data for a package |
MSG_RETRY_CLEAR |
Retry clearing after transport unavailability |
MSG_REQUEST_BACKUP |
Request backup of specific packages |
MSG_SCHEDULE_BACKUP_PACKAGE |
Schedule a package for backup |
MSG_BACKUP_OPERATION_TIMEOUT |
Timeout during backup agent operation |
MSG_RESTORE_OPERATION_TIMEOUT |
Timeout during restore operation |
MSG_RESTORE_SESSION_TIMEOUT |
Timeout for a restore session |
MSG_FULL_CONFIRMATION_TIMEOUT |
User confirmation timeout for full backup |
MSG_OP_COMPLETE |
Operation completion notification |
20.26.6 Backup Eligibility¶
Not all packages are eligible for backup. The BackupEligibilityRules class
determines eligibility based on:
android:allowBackupmanifest attribute (defaulttrue)- Application flags: must not be
STOPPED, must be a real package - Target SDK and backup-specific compat changes
- For key-value backup: must have a declared
BackupAgent - For full backup: can use the default agent if no custom agent specified
- Signature verification: restore data from a different signing key is rejected
20.26.7 Restore Operations¶
Restore is coordinated by PerformUnifiedRestoreTask, which handles both
key-value and full-data restores through a state machine:
stateDiagram-v2
[*] --> INITIAL: Restore requested
INITIAL --> RUNNING_QUEUE: Start processing packages
RUNNING_QUEUE --> RESTORE_KEYVALUE: Key-value package
RUNNING_QUEUE --> RESTORE_FULL: Full-data package
RESTORE_KEYVALUE --> RUNNING_QUEUE: Next package
RESTORE_FULL --> RUNNING_QUEUE: Next package
RUNNING_QUEUE --> FINAL: All packages done
FINAL --> [*]: Cleanup & report
Restores are queued in mPendingRestores and processed serially -- only one
restore can run at a time per user:
// frameworks/base/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@GuardedBy("mPendingRestores")
private boolean mIsRestoreInProgress;
@GuardedBy("mPendingRestores")
private final Queue<PerformUnifiedRestoreTask> mPendingRestores = new ArrayDeque<>();
20.26.8 Cloud vs. Local Backup¶
The transport architecture allows seamless switching between backup destinations:
| Aspect | Cloud Backup (Google) | Local Backup (adb) |
|---|---|---|
| Transport | com.google.android.gms |
com.android.internal.backup.LocalTransport |
| Trigger | JobScheduler (automatic) | adb backup command (manual) |
| Encryption | TLS + server-side encryption | Optional user-set password |
| Format | Transport-specific (protobuf) | Tar archive with optional encryption |
| Quota | Limited (25MB key-value, configurable full) | Unlimited |
| Network required | Yes | No |
| File version header | N/A | ANDROID BACKUP\n + version 5 |
The file format for ADB backups is:
// frameworks/base/services/backup/java/com/android/server/backup/UserBackupManagerService.java
public static final int BACKUP_FILE_VERSION = 5;
public static final String BACKUP_FILE_HEADER_MAGIC = "ANDROID BACKUP\n";
public static final String BACKUP_METADATA_FILENAME = "_meta";
public static final int BACKUP_METADATA_VERSION = 1;
public static final int BACKUP_WIDGET_METADATA_TOKEN = 0x01FFED01;
20.26.9 Multi-User Considerations¶
BMS handles edge cases around multi-user devices:
- The main user might not exist at boot time (first boot), tracked via
mDidMainUserExistAtBoot - Non-system user backup state is stored in both the user's directory
and the system directory -- when a user is removed, BMS cleans up the
system-dir portion via
onRemovedNonSystemUser() - Each user gets an independent
UserBackupManagerServicewith its own transports, schedules, and state
20.27 CrashRecoveryModule and RescueParty¶
When Android detects persistent crashes -- whether from apps, system services,
or boot loops -- the crash recovery subsystem progressively escalates through
increasingly aggressive mitigations to restore the device to a functional state.
This system is built on three cooperating components: PackageWatchdog,
RescueParty, and CrashRecoveryModule.
Key source files:
| File | Description |
|---|---|
frameworks/base/packages/CrashRecovery/services/platform/java/com/android/server/crashrecovery/CrashRecoveryModule.java |
Module lifecycle |
frameworks/base/packages/CrashRecovery/services/platform/java/com/android/server/PackageWatchdog.java |
Failure monitoring engine |
frameworks/base/packages/CrashRecovery/services/platform/java/com/android/server/RescueParty.java |
Escalating mitigation logic |
frameworks/base/services/core/java/com/android/server/crashrecovery/CrashRecoveryHelper.java |
Connectivity module health listener |
20.27.1 CrashRecoveryModule Lifecycle¶
CrashRecoveryModule is delivered as an APEX module and follows the
SystemService lifecycle:
// frameworks/base/packages/CrashRecovery/services/platform/java/com/android/server/crashrecovery/CrashRecoveryModule.java
public static class Lifecycle extends SystemService {
@Override
public void onStart() {
RescueParty.registerHealthObserver(mSystemContext);
mPackageWatchdog.registerShutdownBroadcastReceiver();
mPackageWatchdog.noteBoot();
}
@Override
public void onBootPhase(int phase) {
if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
mPackageWatchdog.onPackagesReady();
}
}
}
At onStart(), three critical actions happen:
- RescueParty registers itself as a health observer with PackageWatchdog
- PackageWatchdog registers to listen for shutdown broadcasts
- PackageWatchdog records the boot event (for boot loop detection)
At boot phase 600 (PHASE_THIRD_PARTY_APPS_CAN_START), PackageWatchdog
initializes its health check controller and begins monitoring.
20.27.2 PackageWatchdog¶
PackageWatchdog is the central failure monitoring engine. It tracks package health through multiple failure signals and delegates mitigation to registered observers.
graph TB
subgraph "Failure Sources"
APP_CRASH["App Crash<br/>(ActivityManagerService)"]
ANR["App Not Responding<br/>(ActivityManagerService)"]
NATIVE["Native Crash<br/>(tombstone polling)"]
HEALTH["Explicit Health Check<br/>(system packages)"]
BOOT["Boot Loop<br/>(boot count tracking)"]
end
subgraph "PackageWatchdog"
NOTIFY["notifyPackageFailure()"]
COUNT["Failure Counter<br/>(5 failures in 1 minute)"]
SELECT["Select Observer<br/>(least user impact)"]
MITIGATE["Execute Mitigation"]
end
subgraph "Health Observers"
RP["RescueParty<br/>(system packages)"]
ROLLBACK["RollbackManager<br/>(mainline modules)"]
end
APP_CRASH --> NOTIFY
ANR --> NOTIFY
NATIVE --> NOTIFY
HEALTH --> NOTIFY
BOOT --> NOTIFY
NOTIFY --> COUNT
COUNT -->|"threshold exceeded"| SELECT
SELECT --> RP
SELECT --> ROLLBACK
RP --> MITIGATE
ROLLBACK --> MITIGATE
Failure reasons:
// frameworks/base/packages/CrashRecovery/services/platform/java/com/android/server/PackageWatchdog.java
public static final int FAILURE_REASON_UNKNOWN = 0;
public static final int FAILURE_REASON_NATIVE_CRASH = 1;
public static final int FAILURE_REASON_EXPLICIT_HEALTH_CHECK = 2;
public static final int FAILURE_REASON_APP_CRASH = 3;
public static final int FAILURE_REASON_APP_NOT_RESPONDING = 4;
public static final int FAILURE_REASON_BOOT_LOOP = 5;
Trigger thresholds:
| Parameter | Default | Description |
|---|---|---|
DEFAULT_TRIGGER_FAILURE_COUNT |
5 | Failures needed to trigger mitigation |
DEFAULT_TRIGGER_FAILURE_DURATION_MS |
60,000ms (1 min) | Window for counting failures |
DEFAULT_OBSERVING_DURATION_MS |
2 days | How long to monitor a package |
DEFAULT_DEESCALATION_WINDOW_MS |
1 hour | Sliding window for mitigation count |
DEFAULT_BOOT_LOOP_TRIGGER_COUNT |
5 | Boots to detect a boot loop |
DEFAULT_BOOT_LOOP_TRIGGER_WINDOW_MS |
10 min | Window for boot loop detection |
When notifyPackageFailure() is called, the watchdog:
- Records the failure timestamp for the package
- Counts failures within the trigger window
- If the threshold is exceeded, selects the registered observer with the
lowest user impact (using
PackageHealthObserverImpactlevels) - Calls the observer's mitigation method
- Records the mitigation for de-escalation tracking
Observer registration and selection:
// Each observer registers with PackageWatchdog
PackageWatchdog.getInstance(context).registerHealthObserver(
null, RescuePartyObserver.getInstance(context));
When multiple observers are registered (e.g., RescueParty and RollbackManager), the watchdog selects the one whose mitigation has the least user impact. This ensures a package rollback is preferred over a factory reset.
State persistence:
PackageWatchdog persists its observer state to /data/system/package-watchdog.xml
using the AtomicFile mechanism. Boot loop mitigation counts are stored
separately in /metadata/watchdog/mitigation_count.txt to survive filesystem
checkpoint aborts.
20.27.3 RescueParty Escalation Levels¶
RescueParty registers as a PackageHealthObserver and implements a graduated
escalation strategy. Each successive mitigation attempt escalates to a more
aggressive level:
flowchart TB
subgraph "Legacy Escalation (pre-flag)"
L1["Level 1: Reset untrusted<br/>settings to defaults"]
L2["Level 2: Reset untrusted<br/>settings changes"]
L3["Level 3: Reset trusted<br/>settings to defaults"]
L4["Level 4: Warm reboot"]
L5["Level 5: Factory reset"]
L1 --> L2 --> L3 --> L4 --> L5
end
subgraph "New Escalation (recoverabilityDetection flag)"
N1["Level 1: Scoped DeviceConfig<br/>reset (per-package)"]
N2["Level 2: All DeviceConfig<br/>reset"]
N3["Level 3: Warm reboot"]
N4["Level 4: Reset untrusted<br/>settings defaults"]
N5["Level 5: Reset untrusted<br/>settings changes"]
N6["Level 6: Reset trusted<br/>settings defaults"]
N7["Level 7: Factory reset"]
N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
end
subgraph "Simplified Escalation (deprecateFlagsAndSettingsResets flag)"
S1["Level 1: Warm reboot"]
S2["Level 2: Factory reset"]
S1 --> S2
end
The escalation constants:
// frameworks/base/packages/CrashRecovery/services/platform/java/com/android/server/RescueParty.java
static final int RESCUE_LEVEL_NONE = 0;
static final int RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET = 1;
static final int RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET = 2;
static final int RESCUE_LEVEL_WARM_REBOOT = 3;
static final int RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS = 4;
static final int RESCUE_LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES = 5;
static final int RESCUE_LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS = 6;
static final int RESCUE_LEVEL_FACTORY_RESET = 7;
20.27.4 RescueParty Disable Conditions¶
RescueParty is deliberately disabled in several scenarios to avoid interfering with development and testing:
- Engineering builds (
Build.TYPE.equals("eng")) -- Always disabled - USB-connected userdebug -- Disabled when USB is active on userdebug builds, indicating active debugging
- DeviceConfig flag --
persist.device_config.configuration.disable_rescue_party - Manual property --
persist.sys.disable_rescuefor emergency override - Explicit enable --
persist.sys.enable_rescueoverrides all disable checks
// frameworks/base/packages/CrashRecovery/services/platform/java/com/android/server/RescueParty.java
// We're disabled on userdebug devices connected over USB, since that's
// a decent signal that someone is actively trying to debug the device,
// or that it's in a lab environment.
if (Build.TYPE.equals("userdebug") && isUsbActive()) {
Slog.v(TAG, "Disabled because of active USB connection");
return true;
}
20.27.5 Boot Loop Detection¶
Boot loops are detected by PackageWatchdog.BootThreshold:
Boot loop detection:
- Track: mBootThreshold(count=5, window=10min)
- PackageWatchdog.noteBoot() called at every system_server start
- If 5 boots occur within 10 minutes → FAILURE_REASON_BOOT_LOOP
- Boot loop failures skip per-package scoped mitigations
(no package to blame → go straight to global mitigations)
When a boot loop is detected without a specific failing package, the mitigation count offset shifts by 1 because scoped DeviceConfig reset is meaningless without a target package.
20.27.6 Factory Reset Throttling¶
To prevent rapid factory reset cycles, RescueParty implements throttling:
// frameworks/base/packages/CrashRecovery/services/platform/java/com/android/server/RescueParty.java
static final long DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN = 1440; // 24 hours
The CrashRecoveryProperties system stores:
attemptingFactoryReset-- Whether a factory reset is in progressattemptingReboot-- Whether a reboot is in progresslastFactoryResetTimeMs-- Timestamp of last factory resetmaxRescueLevelAttempted-- Highest level ever reached
20.27.7 CrashRecoveryHelper¶
The CrashRecoveryHelper class bridges PackageWatchdog with the
connectivity module health monitoring:
// frameworks/base/services/core/java/com/android/server/crashrecovery/CrashRecoveryHelper.java
public void registerConnectivityModuleHealthListener() {
mConnectivityModuleConnector.registerHealthListener(
packageName -> {
final VersionedPackage pkg = getVersionedPackage(packageName);
if (pkg == null) {
Slog.wtf(TAG, "NetworkStack failed but could not find its package");
return;
}
final List<VersionedPackage> pkgList = Collections.singletonList(pkg);
PackageWatchdog.getInstance(mContext).notifyPackageFailure(pkgList,
PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
});
}
This ensures network stack crashes are funneled through the same PackageWatchdog pipeline as other failures, enabling consistent mitigation (including potential rollback of the Tethering APEX).
20.27.8 Integration with RollbackManager¶
PackageWatchdog works alongside RollbackManager for mainline module
crash recovery:
sequenceDiagram
participant AMS as ActivityManagerService
participant PW as PackageWatchdog
participant RP as RescueParty
participant RM as RollbackManager
AMS->>PW: notifyPackageFailure(modulePackage, APP_CRASH)
PW->>PW: Count failures (5 in 1 min?)
alt Rollback available
PW->>RM: onHealthCheckFailed(modulePackage)
RM->>RM: Rollback APEX/APK update
Note over RM: Lower user impact than RescueParty
else No rollback available
PW->>RP: execute(modulePackage, mitigationCount)
RP->>RP: Escalate through rescue levels
end
The key principle is least user impact: rollback (restoring the previous version) is always preferred over settings resets or factory reset because it is less disruptive.
20.28 ClipboardService¶
The ClipboardService manages the system clipboard -- the mechanism that
enables copy-and-paste across applications. What seems like a trivial
feature involves deep security considerations: cross-app data leakage,
content URI permission grants, multi-user isolation, virtual device
clipboard silos, automatic clipboard clearing, and access notification
toasts.
Source:
frameworks/base/services/core/java/com/android/server/clipboard/ClipboardService.java
20.28.1 Architecture Overview¶
ClipboardService extends SystemService and publishes two interfaces on
startup:
// ClipboardService.java, line 251-254
@Override
public void onStart() {
publishBinderService(Context.CLIPBOARD_SERVICE, new ClipboardImpl());
LocalServices.addService(ClipboardManagerInternal.class, new ClipboardInternalImpl());
}
The dual interface follows the standard system_server pattern:
ClipboardImpl (Binder) for app-facing IPC, and ClipboardInternalImpl
(local) for intra-process use by other system services.
graph TD
App["Application"] -->|"IClipboard (Binder)"| CI["ClipboardImpl"]
CI --> CS["ClipboardService"]
SS["Other System Services"] -->|"ClipboardManagerInternal (local)"| IL["ClipboardInternalImpl"]
IL --> CS
CS --> CB["Clipboard objects<br/>(per userId + deviceId)"]
CS --> UGM["UriGrantsManager<br/>(permission grants)"]
CS --> AO["AppOpsManager<br/>(access control)"]
CS --> TC["TextClassifier<br/>(content classification)"]
20.28.2 The Clipboard Data Model¶
Clipboard data is stored in Clipboard objects indexed by a composite key
of (userId, deviceId):
// ClipboardService.java, line 182
@GuardedBy("mLock")
private final SparseArrayMap<Integer, Clipboard> mClipboards = new SparseArrayMap<>();
Each Clipboard instance holds:
| Field | Type | Purpose |
|---|---|---|
primaryClip |
ClipData |
The actual clipboard content |
primaryClipUid |
int |
UID of the app that set the clip |
mPrimaryClipPackage |
String |
Package that set the clip |
primaryClipListeners |
RemoteCallbackList |
Registered change listeners |
mNotifiedUids |
SparseBooleanArray |
UIDs already shown access toast |
mNotifiedTextClassifierUids |
SparseBooleanArray |
UIDs already sent to classifier |
mTextClassifier |
TextClassifier |
Session for content annotation |
ClipData itself is the framework's representation of clipboard content. It
wraps a ClipDescription (MIME types) and one or more ClipData.Item
objects. Each item can carry plain text, HTML text, an Intent, or a
content Uri. The MIME types supported include:
MIMETYPE_TEXT_PLAIN-- simple textMIMETYPE_TEXT_HTML-- HTML markupMIMETYPE_TEXT_INTENT-- an IntentMIMETYPE_TEXT_URILIST-- content URIsMIMETYPE_APPLICATION_SHORTCUT-- launcher shortcutsMIMETYPE_APPLICATION_ACTIVITY-- activity referencesMIMETYPE_APPLICATION_TASK-- task references
20.28.3 Cross-App Security Restrictions¶
The clipboard is a high-value attack vector because any app can read data placed by any other app. Android enforces several layers of protection:
AppOps gating. Every read and write goes through AppOpsManager:
// clipboardAccessAllowed checks both OP_READ_CLIPBOARD and OP_WRITE_CLIPBOARD
if (!clipboardAccessAllowed(
AppOpsManager.OP_READ_CLIPBOARD, pkg, attributionTag,
intendingUid, intendingUserId, intendingDeviceId)) {
return null;
}
Content URI permission grants. When a ClipData contains a content URI,
the clipboard service grants temporary read permissions to the reading app
via UriGrantsManager. This is the addActiveOwnerLocked() call that runs
when getPrimaryClip() is invoked.
User isolation. Each Android user gets a separate clipboard namespace.
The getIntendingUserId() method validates cross-user access through
ActivityManagerInternal.handleIncomingUser(), requiring either
INTERACT_ACROSS_USERS_FULL or INTERACT_ACROSS_USERS permission.
Device lock check. If the user profile is locked (device locked, FBE credential-encrypted storage not yet available), clipboard reads return null:
20.28.4 Clipboard Access Notification¶
Starting with Android 12, the system shows a toast notification whenever an
app reads the clipboard. This is the "Pasted from
// ClipboardService.java, line 161
private static final long ACCESS_NOTIFICATION_SUPPRESSION_TIMEOUT_MILLIS = 1000L;
The notification is suppressed for 1 second after a previous notification for
the same UID, preventing toast spam when apps read the clipboard multiple
times rapidly. The feature is controlled by a per-user setting
(CLIPBOARD_SHOW_ACCESS_NOTIFICATIONS) and a server-side DeviceConfig flag.
The showAccessNotificationLocked() method also sends the clipboard content
to the TextClassifier for content-type logging via
notifyTextClassifierLocked(), which classifies up to
mMaxClassificationLength (default 400) characters.
20.28.5 Automatic Clipboard Clearing¶
To reduce the window during which sensitive data (passwords, credit cards) sits on the clipboard, the service implements auto-clear:
// ClipboardService.java, line 139
public static final long DEFAULT_CLIPBOARD_TIMEOUT_MILLIS = 3600000; // 1 hour
When setPrimaryClip() is called, the service schedules a delayed
ClipboardClearHandler.MSG_CLEAR message. The timeout (default 1 hour)
and the feature toggle are both controlled via DeviceConfig:
if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_CLIPBOARD,
PROPERTY_AUTO_CLEAR_ENABLED, true)) {
mClipboardClearHandler.sendMessageDelayed(clearMessage,
getTimeoutForAutoClear());
}
If the user pastes the content before the timeout, a new timer is rescheduled from the paste time, giving the user another full timeout window.
20.28.6 Virtual Device Clipboard Silos¶
With the introduction of virtual devices (CDM -- Companion Device Manager), clipboard isolation becomes more complex. Apps running on a virtual device can have a separate clipboard from the default device:
// getIntendingDeviceId() determines which clipboard an app should access
private int getIntendingDeviceId(int requestedDeviceId, int uid) {
if (mVdmInternal == null) {
return DEVICE_ID_DEFAULT;
}
ArraySet<Integer> virtualDeviceIds = mVdmInternal.getDeviceIdsForUid(uid);
// ...
}
The policy is controlled per virtual device via
VirtualDeviceManager.getDevicePolicy(deviceId, POLICY_TYPE_CLIPBOARD).
When DEVICE_POLICY_CUSTOM is set, the virtual device shares the default
clipboard. Otherwise, it gets its own isolated clipboard. When a virtual
device is closed, the VirtualDeviceListener callback removes its clipboard.
graph LR
subgraph "Default Device"
DC["Clipboard<br/>(userId=0, deviceId=DEFAULT)"]
end
subgraph "Virtual Device 1"
VC1["Clipboard<br/>(userId=0, deviceId=1)"]
end
subgraph "Virtual Device 2 (shared)"
VC2["Uses Default Clipboard<br/>(DEVICE_POLICY_CUSTOM)"]
end
VC2 -.->|"shares"| DC
20.28.7 Emulator and ARC Integration¶
ClipboardService detects the execution environment at construction time and installs an appropriate clipboard monitor:
// ClipboardService.java, line 223-238
if (Build.IS_EMULATOR) {
mClipboardMonitor = new EmulatorClipboardMonitor(/* callback */);
} else if (Build.IS_ARC) {
mClipboardMonitor = new ArcClipboardMonitor(/* callback */);
} else {
mClipboardMonitor = (clip) -> {};
}
The EmulatorClipboardMonitor syncs the clipboard between the Android
emulator and the host machine. ArcClipboardMonitor enables clipboard
sharing between the ChromeOS host and the Android container in ARC
(Android Runtime for Chrome).
20.29 DownloadManager and DownloadProvider¶
The download subsystem provides a system-level download service that handles
background HTTP downloads with notification integration, retry logic, network
constraint awareness, and MediaStore integration. Unlike most system
services, the download infrastructure is split between a system API
(DownloadManager) and a separate ContentProvider process
(DownloadProvider).
Source root:
packages/providers/DownloadProvider/src/com/android/providers/downloads/
20.29.1 Architecture¶
graph TD
App["Application"] -->|"DownloadManager API"| DM["DownloadManager"]
DM -->|"ContentResolver.insert()"| DP["DownloadProvider<br/>(ContentProvider)"]
DP -->|"schedules"| JS["DownloadJobService<br/>(JobScheduler)"]
JS -->|"spawns"| DT["DownloadThread"]
DT -->|"HTTP request"| Net["Network"]
DT -->|"progress updates"| DP
DT -->|"notifications"| DN["DownloadNotifier"]
DT -->|"media scanning"| DS["DownloadScanner"]
DP -->|"SQLite"| DB["downloads.db"]
style DP fill:#f9f,stroke:#333
style DT fill:#bbf,stroke:#333
The key components are:
| Component | File | Role |
|---|---|---|
DownloadProvider |
DownloadProvider.java |
ContentProvider managing the downloads database |
DownloadJobService |
DownloadJobService.java |
JobService hosting download execution threads |
DownloadThread |
DownloadThread.java |
Performs the actual HTTP download on a background thread |
DownloadNotifier |
DownloadNotifier.java |
Manages download progress/completion notifications |
DownloadInfo |
DownloadInfo.java |
In-memory representation of a download's state |
DownloadScanner |
DownloadScanner.java |
Triggers MediaStore scanning for completed downloads |
Constants |
Constants.java |
Retry limits, timeout values, other constants |
20.29.2 The Download Database¶
DownloadProvider uses a SQLite database (downloads.db, version 114) with a
single downloads table. The database tracks every download's URI, file
path, status, bytes downloaded, MIME type, notification visibility, retry
count, ETag, and more.
// DownloadProvider.java, line 97-101
private static final String DB_NAME = "downloads.db";
private static final int DB_VERSION = 114;
private static final String DB_TABLE = "downloads";
private static final int IDLE_CONNECTION_TIMEOUT_MS = 30000;
URI matching routes requests through a standard UriMatcher:
| URI Pattern | Constant | Description |
|---|---|---|
downloads/my_downloads |
MY_DOWNLOADS |
Downloads belonging to calling UID |
downloads/my_downloads/# |
MY_DOWNLOADS_ID |
Individual download by calling UID |
downloads/all_downloads |
ALL_DOWNLOADS |
All downloads (requires permission) |
downloads/all_downloads/# |
ALL_DOWNLOADS_ID |
Individual download (any UID) |
20.29.3 Download Execution with JobScheduler¶
Each download is executed as a job in DownloadJobService. When a new
download is inserted into the provider, a job is scheduled. The service
maintains a SparseArray<DownloadThread> of active threads:
// DownloadJobService.java, line 57-76
@Override
public boolean onStartJob(JobParameters params) {
final int id = params.getJobId();
final DownloadInfo info = DownloadInfo.queryDownloadInfo(this, id);
if (info == null) {
return false;
}
final DownloadThread thread;
synchronized (mActiveThreads) {
if (mActiveThreads.indexOfKey(id) >= 0) {
return false; // Already running
}
thread = new DownloadThread(this, params, info);
mActiveThreads.put(id, thread);
}
thread.start();
return true;
}
The job timeout is 10 minutes (standard JobScheduler limit). If a download does not finish, the job is rescheduled and the download resumes using HTTP Range headers and the stored ETag.
20.29.4 Retry Logic¶
DownloadThread implements a retry mechanism with exponential backoff:
// Constants.java, line 143-155
public static final int MAX_RETRIES = 5;
public static final int MIN_RETRY_AFTER = 30; // 30 seconds
public static final int MAX_RETRY_AFTER = 24 * 60 * 60; // 24 hours
When an error occurs, the thread distinguishes between retryable and permanent failures:
flowchart TD
E["Error occurs"] --> R{"Is status retryable?"}
R -->|"Yes"| P{"Made progress?"}
P -->|"Yes"| Reset["Reset fail count to 1"]
P -->|"No"| Inc["Increment fail count"]
Reset --> C{"numFailed < MAX_RETRIES (5)?"}
Inc --> C
C -->|"Yes"| Net{"Network available?"}
Net -->|"Yes"| Retry["STATUS_WAITING_TO_RETRY<br/>(backoff delay)"]
Net -->|"No"| Wait["STATUS_WAITING_FOR_NETWORK"]
C -->|"No"| Fail["Permanent failure"]
R -->|"No"| Fail
The "made progress" check is key: if any data was transferred during the current attempt, the failure counter resets to 1. This prevents a large file download from failing permanently due to intermittent connectivity.
20.29.5 Notification Integration¶
DownloadNotifier manages three notification channels:
| Channel | Importance | Usage |
|---|---|---|
active |
IMPORTANCE_MIN |
Downloads in progress |
waiting |
IMPORTANCE_DEFAULT |
Downloads waiting for network |
complete |
IMPORTANCE_DEFAULT |
Completed or failed downloads |
Download visibility is controlled by the VISIBILITY_* constants set in
the DownloadManager.Request:
VISIBILITY_VISIBLE-- show notification while runningVISIBILITY_VISIBLE_NOTIFY_COMPLETED-- show while running and after completionVISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION-- show only on completionVISIBILITY_HIDDEN-- no notification (requiresDOWNLOAD_WITHOUT_NOTIFICATION)
The notifier tracks active download speeds in a LongSparseLongArray to
calculate and display estimated time remaining.
20.29.6 Network Awareness¶
DownloadThread uses the caller's default network rather than the system
default, respecting per-UID network restrictions:
// DownloadThread.java, line 300-304
mNetwork = mSystemFacade.getNetwork(mParams);
if (mNetwork == null) {
throw new StopRequestException(STATUS_WAITING_FOR_NETWORK,
"No network associated with requesting UID");
}
The thread registers a NetworkPolicyListener to react to policy changes
(metered network restrictions, data saver mode) mid-download. Traffic is
tagged with the requesting UID for proper data accounting:
Summary¶
The system_server process is the largest and most complex process in
Android. It is forked from Zygote and initializes over 100 Java system
services through a carefully ordered four-phase startup sequence:
bootstrap, core, other, and APEX services. Each service extends the
SystemService base class and receives lifecycle callbacks as the
system progresses through eight boot phases from
PHASE_WAIT_FOR_DEFAULT_DISPLAY (100) to PHASE_BOOT_COMPLETED (1000).
The threading model uses eight shared singleton threads (plus the main
looper and a pool of 31 Binder threads), each with a specific priority
level and purpose. The Watchdog monitors all critical threads every 15
seconds and kills system_server if any thread remains unresponsive for
60 seconds, triggering a runtime restart rather than leaving the device
frozen.
Service communication uses a dual-interface pattern: Binder services for cross-process access from apps, and local services for efficient intra-process access from other system services. The lock ordering discipline, ThreadPriorityBooster, and LockGuard mechanisms prevent deadlocks across the hundreds of interacting services.
Performance is optimized through parallel initialization via
SystemServerInitThreadPool, lazy singleton thread creation, Zygote
memory inheritance, and careful boot phase ordering. The APEX module
loading mechanism allows services to be delivered and updated through
mainline modules without modifying SystemServer.java.
Understanding system_server is essential for AOSP development because
virtually every framework API passes through it. Whether you are adding
a new system service, debugging a boot hang, optimizing startup time,
or investigating a Watchdog timeout, the concepts in this chapter --
service lifecycle, boot phases, threading model, Watchdog monitoring,
lock ordering, and the dual-interface communication pattern -- provide
the foundation for working effectively with the Android framework.