Zygote
system_serverintermediate

What system_server is

One Java process hosts most of the framework's services, is forked from Zygote at boot, and takes the whole UI down with it when it dies. This is what lives inside it and why it is shaped that way.

13 minAPI 1–37 · 17interactivequizverified 2026-10-27

Every Android app that calls getSystemService() is talking to a process it never names. That process is system_server: a single Java/Kotlin process, started at boot, hosting the services that decide what runs, what is visible, what is installed and who may do what.

TL;DR#

  • system_server is one process that hosts roughly a hundred framework services. It is forked from at boot, not started from scratch.
  • Each service is a Binder object published under a name in . Apps never address the process; they address a service.
  • It runs with the system UID and a privileged SELinux domain, which is why compromising it is equivalent to compromising the platform.
  • A crash is not an app crash. The framework state is gone, so the system performs a soft reboot that restarts the framework without rebooting the kernel.
  • The thread kills the process when a critical service stops making progress, which is the same path taken by a deadlock.

Mental model#

Think of a city's municipal building.

Every department — planning, licensing, utilities, records — sits in one building, but citizens do not walk into "the building". They go to a counter with a name on it: permits, water, records. The building is an address; the counter is the interface.

That is system_server and its services. The process is the building. ActivityManager, PackageManager, WindowManager are the counters. When you call context.getSystemService(Context.ACTIVITY_SERVICE), you are not getting the building; you are getting a phone line to one counter.

The departments share a building for a reason: they constantly need each other's records. Planning needs the licensing register; utilities needs the planning map. Putting them in one process makes those conversations cheap, because they become method calls rather than Binder transactions.

Where the analogy breaks#

A municipal building is robust: one department can close for renovation. system_server is not. Its services share one heap and one main thread, so a deadlock in the notification service can stop the activity manager from ever handling the next launch. The building is also not merely an address: it holds the authoritative in-memory state of the running system. There is no database to fall back on. That is why the recovery strategy is not "restart the department" but "restart the municipality" — the soft reboot.

The big picture#

system_server is best understood as a neighbourhood rather than a list. The services cluster by the question they answer.

Loading diagram…
Text description of this diagram

A treemap of system_server's services grouped into seven areas: activity and windows (ActivityTaskManager, ActivityManager, WindowManager, InputManager, DisplayManager, InputMethodManager, DreamManager, WallpaperManager, AccessibilityManager), packages and users (PackageManager, PermissionManager, UserManager, LauncherApps, ShortcutManager, AppWidgetService, DevicePolicyManager, CredentialManager, LocaleManager), power and time (PowerManager, AlarmManager, JobScheduler, BatteryStats, NetworkPolicy, DeviceStateManager, ThermalService), media and audio (AudioManager, MediaSessionService, MediaProjectionManager, CameraService, MidiService, SoundTrigger, PrintManager), connectivity (ConnectivityService, WifiService, TelephonyManager, BluetoothManager, Vpn, NetworkStats, NfcService), security and identity (KeyStoreService, BiometricService, FingerprintService, TrustManager, KeyguardServiceDelegate, AppOpsService, IncidentManager), and system and diagnostics (StorageManagerService, UsbService, ClipboardService, DropBoxManager, BugreportManager, StatsCompanion, UsageStatsService, HardwarePropertiesManager, VibratorManager). Each block is one registered Binder service; its size is its share of the catalogue, not of the process's memory.

The grouping matters more than the inventory. The services that answer "what is running" and the services that answer "what is installed" are the two poles the rest of the platform revolves around. Everything else — power, media, connectivity, security — is a specialist that both poles consult.

Where the process comes from#

system_server is not launched by init the way surfaceflinger or audioserver are. It is forked by Zygote, which means it starts life as a copy of a process that has already loaded the framework classes and initialised ART. The sequence is worth knowing because it explains both its speed and its privilege.1

  1. init starts zygote from an .rc file.
  2. Zygote preloads classes and resources, then listens on a Unix socket.
  3. init starts the system_server service, which connects to that socket and asks Zygote to fork.
  4. The child runs SystemServer's main, which spawns the services.

The fork is why system_server does not pay seconds of class-loading at every boot, and why its heap starts with a large shared read-only region inherited from Zygote. It is also why a bug in a preloaded class affects every process on the device.

The boot phases#

SystemServer.java reports progress through a small set of phase constants. They are the single best map of what has to happen before a phone is usable, and they appear in logcat and in dumpsys timing output.

Loading diagram…
Text description of this diagram

A timeline of system_server's boot phases plotted against the numeric phase constants used in SystemServer.java. PHASE_WAIT_FOR_DEFAULT_DISPLAY is 100: the process waits for a display to exist. PHASE_WAIT_FOR_SENSOR_SERVICE is 200: it waits for the sensor service. PHASE_LOCK_SETTINGS_READY is 480: credential and keystore state can be read. PHASE_SYSTEM_SERVICES_READY is 500: the framework's own services are registered. PHASE_DEVICE_SPECIFIC_SERVICES_READY is 520: OEM and vendor services have hooked in. PHASE_ACTIVITY_MANAGER_READY is 550: activities can be launched. PHASE_THIRD_PARTY_APPS_CAN_START is 600: the lock screen is up and ordinary apps may start. PHASE_BOOT_COMPLETED is 1000: BOOT_COMPLETED broadcasts are delivered. The large gap between 200 and 480 is where the native services and HALs are brought up.

Two things are easy to miss in that list.

The first is that PHASE_DEVICE_SPECIFIC_SERVICES_READY exists at all. There is a documented seam where an OEM can add services to the boot sequence without forking SystemServer.java. That seam is a compromise: vendor code needs to run at boot, and the platform would rather give it a hook than a fork.

The second is the ordering constraint at 480. Lock settings must be ready before user and keyguard services can do anything meaningful, because their state lives behind the user's credential. On a device with File-Based Encryption, that is the moment the framework can begin reasoning about credential-encrypted storage at all.

Deep dive#

One process, many services#

The class that starts everything is SystemServer.java.1 Its run() method is a long sequence of startService-style calls, most of which follow the same shape: build a *Service object, register it with ServiceManager, and keep a static reference for in-process callers.

Registration is by name, and the name is what matters. ActivityManagerService is published as "activity". WindowManagerService is "window". PackageManagerService is "package".1 Those strings are the keys that <G id="binder">Binder</G> clients use, and they are stable in a way the Java class names are not — services get renamed and split, but the binder name has to keep working or every app on the device breaks.

The mapping from a Context constant to a binder name is in SystemServiceRegistry.java. That file is a static block with one registerService call per service. It is the closest thing to an official inventory, and it is where you look when you want to know what getSystemService will actually return for a given constant.22

The privilege question#

system_server runs as the system user, not as root. That surprises people who assume the framework is omnipotent.3 It has a great many permissions and a privileged SELinux domain, but it still goes through the same kernel checks as anything else. When a framework service reads an app's file, SELinux is consulted exactly as it would be for another app.

This is deliberate. The design goal is that a compromise of the framework is bad but not unbounded: the kernel and the secure hardware are still in front of the keys. It is the same defence-in-depth argument that puts a TEE in front of Keystore, applied one layer up.

What happens when it crashes#

If system_server dies, every service it hosted dies with it. Binder proxies held by apps become dead objects. Windows lose their owner. The activity stack, the package state and the notification state are gone.

The recovery path is the soft reboot: the framework restarts while the kernel and the native services keep running. On modern Android this is implemented as a controlled restart of the framework rather than a full device reboot, which is why you sometimes see a phone return to the lock screen in a few seconds without the boot logo.4

It is worth being precise about what survives. The kernel survives. surfaceflinger, audioserver and the HALs survive. What does not survive is every process that held a Binder reference to a framework service: in practice, that means every app. That is why a soft reboot feels like a reboot even though the uptime counter keeps climbing.

The Watchdog#

The is a thread inside system_server that periodically checks whether the main thread and a set of critical services are making progress. It uses a HandlerChecker per monitored thread and a monotonic clock, and it is deliberately dumb: it does not try to diagnose, it tries to notice.

If a monitored thread fails to respond within its timeout, the Watchdog logs a trace and kills the process. The kill is the point: a hung system_server is worse than a restarting one, because a hung one holds the locks that every other service needs.

What is not in the process#

A useful sanity check on the mental model: several things that feel like framework services are not in this process.

  • SurfaceFlinger is a native process. WindowManagerService decides where windows go; SurfaceFlinger does the composition.
  • audioserver does the mixing. AudioManager in system_server is policy and routing.
  • The camera provider is a vendor HAL process. CameraService arbitrates between clients.
  • vold is a native daemon that mounts storage. StorageManagerService is the policy layer.
  • MediaCodec runs in app processes via mediaserver and vendor codecs.

The pattern is consistent: system_server holds policy and bookkeeping, and the heavy or device-specific work happens elsewhere. That division is why a framework restart can leave audio playing for a moment, and why a camera HAL crash does not take the launcher with it.

How it evolved#

The process has been continuously debloated. Services are split out when they get too large, moved into Mainline modules when they need to update independently, and occasionally moved out of the process entirely.

Architecture changes29 releases
APIVersionWhat changed
11.0
  • Initial AOSP platform: Linux kernel, Dalvik VM, core libraries
  • The first zygote-based app spawning model
41.6 Donut
  • Support for different screen densities via resource qualifiers
52.0 Eclair
  • First multi-core-friendly scheduling and graphics work
82.2 Froyo
  • Trace-based JIT compiler added to Dalvik
  • Support for x86 and ARMv7 optimisations
92.3 Gingerbread
  • Concurrent garbage collector added to Dalvik (GC pause reduction)
113.0 Honeycomb
  • Hardware acceleration for the View system (opt-in per app)
133.2 Honeycomb
  • New screen-size resource qualifiers for compatibility scaling
144.0 Ice Cream Sandwich
  • One system image for phones and tablets
  • Hardware acceleration on by default
164.1 Jelly Bean
  • Project Butter: vsync, triple buffering, Choreographer
  • RenderThread architecture begins
174.2 Jelly Bean
  • Multi-user support on tablets
  • SELinux enforcement begins in the kernel (behind the scenes)
184.3 Jelly Bean
  • SELinux enforcement rolled out more broadly
  • Binder changes for restricted profiles
194.4 KitKat
  • Android Runtime (ART) appears as an experimental runtime
  • Kernel moved under a tighter vendor control
204.4W KitKat (Wear)
  • First time the platform shipped for a new form factor
215.0 Lollipop
  • ART becomes the only runtime: ahead-of-time compilation at install
  • 64-bit ARM and x86 support
  • RenderThread and OpenGL ES 3.1
  • Project Volta and JobScheduler
  • SELinux fully enforcing
225.1 Lollipop
  • Device protection ties verified boot to Google accounts
236.0 Marshmallow
  • Runtime permission model changes how every app asks for access
  • Doze batches background work
  • Fingerprint HAL
  • Adoptable storage
247.0 Nougat
  • Project Treble groundwork
  • A/B seamless updates
  • Hybrid JIT + AOT compilation in ART
  • MediaServer split into sandboxed processes
268.0 Oreo
  • Project Treble: the vendor interface separates vendor and system code
  • Background execution limits
  • Broadcast and service restrictions
  • HIDL for HALs
278.1 Oreo
  • Android Go: a lighter configuration of the same platform
289 Pie
  • App Standby Buckets
  • Mainline groundwork
  • Non-SDK interface restrictions (greylists) begin
  • BiometricPrompt
2910
  • Project Mainline: APEX and updatable system modules
  • Scoped storage
  • Bubbles
  • Project Mainline starts shipping through Play
3011
  • GKI: the Generic Kernel Image splits the kernel into core + vendor modules
  • App hibernation
  • Package visibility filtering
  • Incremental app installs
3112
  • Bluetooth permissions split into the nearby-devices family
  • Exact alarm permissions
  • Foreground service launch restrictions
3212L
  • Window size classes and activity embedding
3313 Tiramisu
  • Granular media permissions replace READ_EXTERNAL_STORAGE
  • The notification permission becomes a runtime permission
  • Predictive back gesture
3414 Upside Down Cake
  • Foreground service types are mandatory
  • Selected photos access via READ_MEDIA_VISUAL_USER_SELECTED
3515 Vanilla Ice Cream
  • 16 KB page size support for native libraries
  • Edge-to-edge is enforced when targeting 35
3616 Baklava
  • The release moves to Q2 (June) with a Q4 feature drop
  • Two SDK releases per year starting with 36
  • Desktop windowing arrives in developer options then stable
3717 Cinnamon Bun
  • Strict per-device app memory limits are enforced by the system
  • Generational garbage collection is added to ART's Concurrent Mark-Compact collector
  • A lock-free MessageQueue for apps targeting API 37
  • Compose-first: new platform and Jetpack APIs target Compose only; View libraries enter maintenance mode
  • Hybrid APK signing (v3.2) combines classical and ML-DSA post-quantum signatures
  • Native library dynamic code loading must be read-only

Two splits are worth knowing by name. ActivityTaskManagerService was carved out of ActivityManagerService in Android 10 to separate activity/task management from process management. PermissionManagerService was carved out of PackageManagerService in Android 11 to separate permission policy from package state. Both are the same story: a class that had grown to do two jobs was cut along the seam between them.

Under the hood#

Curiosity corner#

  • system_server is the largest Java heap on an idle phone. Its heap is dominated by the activity stack, the package database and the resource caches, not by your apps. That is why dumpsys meminfo shows it near the top even when nothing is happening.
  • The process has a fixed name, but not a fixed contents list. Services have been added, split and moved out for seventeen API levels; the name system_server has not changed since Android 1.0.
  • The soft reboot has a user-visible tell. If your phone returns to the lock screen without the boot animation, you probably just watched the framework restart after a Watchdog kill.

Try it#

Confirm the fork and the services

adb shell ps -A -o USER,PID,PPID,NAME | grep -E "system_server|zygote" adb shell service list | head -20

Example output
system        863   610  system_server
root          610     1  zygote64

The second command prints every registered Binder service with its interface descriptor. It is the closest thing to system_server's table of contents, and it is the list getSystemService is ultimately indexing.

Check yourself#

Check yourself

1 / 12

How does system_server's process come into existence at boot?

0 answered · 0 correct

Sources#

Sources

Every version number, API level, class name and date on this page is traced to one of these. Pages are re-verified against them; last_verified above says when.

  1. docsAndroid platform architecture (AOSP)source.android.comaccessed 2026-10-27↩
  2. docsContext | API referencedeveloper.android.comaccessed 2026-10-27↩
  3. docsApplication sandboxsource.android.comaccessed 2026-10-27↩
  4. docsSoft restartsource.android.comaccessed 2026-10-27↩
  5. docsProcesses and threads overview | App qualitydeveloper.android.comaccessed 2026-10-27↩
  6. docsZygotesource.android.comaccessed 2026-10-27↩