Zygote
Notifications & SystemUInerd

SystemUI

The status bar, the shade, quick settings, the lock screen and the navigation bar are all drawn by one privileged app. SystemUI is not part of the framework — it is an APK that holds special powers and can crash without taking the system down.

12 minAPI 21–37 · 17interactivequizverified 2026-10-27

SystemUI is the part of Android that feels like the operating system and is, in fact, an application. It draws the status bar, the shade, the lock screen, the volume panel and the navigation bar, and it does so from a process that can be killed and restarted.

TL;DR#

  • SystemUI is a privileged system app, not a framework component. It lives in frameworks/base/packages/SystemUI/.
  • It draws the status bar, notification shade, quick settings, lock screen, volume panel, navigation bar and, in some versions, recents.
  • It receives notifications through a privileged listener connection and renders them from RemoteViews.
  • Quick Settings tiles have a public API since Android 7.0; apps can add their own.
  • Its plugins system lets OEMs customise it without forking the whole app.
  • When it crashes, the status bar disappears while the rest of the system keeps running — which is the clearest proof that it is an app.

Mental model#

Think of a hotel's front desk.

The building is the framework and system_server: lifts, plumbing, locks. The front desk does not maintain any of it.

The front desk is SystemUI. It is where guests see their messages, where the lift status is displayed, and where the concierge takes requests. It is staffed by employees who can be replaced without closing the hotel.

The concierge's authority is delegated: the desk can open doors because the building gave it a master key, not because it owns the locks.

Where the analogy breaks#

A front desk is a place. SystemUI is a process with a window that sits above every other window, and its "master key" is a set of signature|privileged permissions plus a direct Binder connection to system_server. The delegation is technical and enumerable, not social.

The big picture#

Loading diagram…
Text description of this diagram

A three-column map of every surface attributed to its real owner. The SystemUI column holds the status bar icons and clock, the notification shade, the Quick Settings panel since API 17 and third-party tiles since API 24, the lock screen keyguard since API 21, the volume panel, and the navigation bar. The system_server column holds NotificationManagerService, which validates and ranks notifications; ActivityManagerService, which owns tasks and processes; and WindowManagerService, which treats the shade and status bar as windows. The launcher column holds the recents and overview gesture since API 28 through Quickstep, and widget hosting since API 3. Three notes below: SystemUI is not in system_server and runs in its own process, so when it ANRs the status bar freezes while the rest of the phone works; its powers come from signature privileged permissions and a build-time listener grant; and it renders app content as RemoteViews descriptions rather than running app code.

The modularity is what allows an OEM to ship a different shade without forking the framework, and what allows Google to update parts of SystemUI through Play on supported devices.

Deep dive#

What SystemUI actually draws#

The list is longer than most people expect:

SurfaceNotes
Status barIcons, clock, battery, privacy indicators
Notification shadeThe list of notifications, grouped and ranked
Quick SettingsThe tile grid behind the shade
Lock screenOn many devices, including the notification presentation
Volume panelThe system volume UI
Navigation barGesture and button navigation, in most versions
RecentsHistorically in SystemUI; on modern devices it is part of the launcher (Quickstep)
KeyguardThe lock screen state machine, not the lock screen's visual only

The recents entry is the one that moves. On modern Android, the recents/overview gesture is implemented by the launcher through the Quickstep integration, while SystemUI still owns parts of the transition. That split is a frequent source of confusion when debugging.

The privileged connection#

SystemUI holds a NotificationListenerService grant — the same API available to third-party apps, but granted at build time rather than by the user. Through it, it receives every notification as a StatusBarNotification and renders the content.1

It also holds permissions such as STATUS_BAR, EXPAND_STATUS_BAR and STATUS_BAR_SERVICE, which are signature|privileged and unavailable to ordinary apps.

Quick Settings tiles#

The tile API has been public since Android 7.0 (API 24). A tile is a TileService declared in the manifest with android.service.quicksettings.action.QS_TILE:2

class FocusTileService : TileService() {
 
    override fun onStartListening() {
        qsTile?.apply {
            state = if (isFocusOn()) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
            label = "Focus"
            updateTile()
        }
    }
 
    override fun onClick() {
        toggleFocus()
        qsTile?.apply {
            state = if (isFocusOn()) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
            updateTile()
        }
    }
}

The system binds to the service, calls onStartListening when the shade opens, and onClick when the user taps. The app does not draw the tile; it supplies a state, a label, an icon and optionally a subtitle or a dialog.

The constraint worth knowing: a tile is not a widget. You cannot put arbitrary content in it, which is why tiles are limited to an icon, a label and a state — and why media controls in Quick Settings are a system feature, not a tile.

The plugin architecture#

OEMs need to change SystemUI without forking the whole app, and Google needs to ship a single SystemUI that can look different on different devices. The answer is a plugin system: SystemUI loads implementation classes by interface, and the device's overlay or a plugin APK supplies the implementation.

This is why the AOSP source has a plugins/ directory containing interfaces with names like GlobalActions, NotificationUI, NavBar and Keyguard. The interfaces are the contract; the implementations are replaceable.

Rendering other apps' content safely#

The security problem SystemUI faces is unusual: it must render content supplied by untrusted apps, at high priority, above other windows.1

Three defences matter:

  • RemoteViews allowlist. Only a fixed set of view classes and methods can be inflated from a notification's custom layout.
  • Size limits. A notification's view hierarchy is bounded; the platform rejects layouts that exceed the limits, which is what Android 17's tightening continues.
  • No code execution. The app's process is not involved in rendering. Only a PendingIntent fires app code, and it fires in the app's process with the app's identity.

The lock screen and privacy#

The lock screen is SystemUI's most privacy-sensitive surface. The visibility set on a notification decides whether its content appears there:1

  • VISIBILITY_PUBLIC — the full content is shown.
  • VISIBILITY_PRIVATE — the content is replaced by the app's public version.
  • VISIBILITY_SECRET — nothing is shown.

A notification that sets VISIBILITY_PUBLIC on a messaging app puts message text in front of anyone holding the phone. That is a decision the app makes, and it is frequently the wrong one.

Why SystemUI is a separate app at all#

The separation is not an accident of history; it is a deliberate boundary with three benefits.

Failure isolation. A bug in the shade should not take down the window manager. Because SystemUI is a process, an ANR there freezes the status bar and leaves everything else running. That is a degraded experience, not a dead phone.

Independent updateability. Parts of SystemUI can be updated without a full platform release, which matters more as the module structure matures. The shade is a place where a security fix should not require an OTA.

Replaceability for OEMs. A vendor can ship a different shade, a different quick settings layout or a different lock screen without forking the framework. The plugin architecture exists to make that possible without a fork of the whole app.

The cost is the one every process boundary has: every piece of data SystemUI displays must cross Binder, and every cross-boundary interaction is a place where a size limit or a permission check can intervene.

Debugging the shade#

SystemUI has its own dump and its own logs, and they are the fastest way to understand a rendering problem.

adb shell dumpsys activity service com.android.systemui/.SystemUIService prints the state of the status bar, the shade and the keyguard. Logcat tags beginning with SystemUI cover the row inflation path. When a notification appears in dumpsys notification but not on screen, the problem is almost always in SystemUI's rendering rather than in the notification service, and the two dumps together localise it in a minute.

The difference between "system" and "framework"#

The vocabulary is worth fixing because it explains a lot of Android's behaviour.

The framework is the code in the bootclasspath and system_server: the APIs and the services. It is what an app calls.

The system apps are APKs that ship on the image and hold privileged permissions: SystemUI, Settings, the launcher, the phone app. They call the framework like any app, with a bigger set of permissions.

"System" is therefore a deployment category, not an architectural layer. SystemUI is a system app; the notification service it reads from is a framework service. Confusing the two leads to the wrong mental model of where a bug lives, and to the wrong place to look for a fix.

How it evolved#

2008–2013Monolithicstatus bar and shade tightly coupled to the framework
2014–2016Tiles and lockscreenheads-up, lock screen, quick settings tiles
2017–2019Pluginsplugin architecture and OEM customisation
2020–nowModularMainline-adjacent updates and a public tile API
Interface changes16 releases
APIVersionWhat changed
11.0
  • Pull-down notification shade
  • Home screen with widgets
31.5 Cupcake
  • Home screen widgets and folders
92.3 Gingerbread
  • New UI with dark theme and green accents
113.0 Honeycomb
  • The Holo design language arrives
123.1 Honeycomb
  • Resizable widgets
164.1 Jelly Bean
  • Project Butter: vsync-driven, smooth UI
  • Expandable notifications
204.4W KitKat (Wear)
  • Voice-driven card UI
215.0 Lollipop
  • Material Design
  • Notifications on the lock screen
247.0 Nougat
  • Quick Settings tiles
  • Direct Reply in notifications
268.0 Oreo
  • Notification channels
289 Pie
  • Dark theme groundwork
2910
  • System-wide dark theme
3011
  • Conversation notifications and bubbles
  • Media controls in Quick Settings
3112
  • Material You dynamic colour
3313 Tiramisu
  • Themed app icons
  • Runtime notification permission
3616 Baklava
  • Material 3 Expressive
  • Live Updates notifications

Under the hood#

  • the whole app: status bar, shade, keyguard, QS
  • the notification row inflation and ranking presentation
  • the Quick Settings implementation
  • the plugin interfaces OEMs implement
  • the lock screen state machine

Curiosity corner#

  • SystemUI has its own ANR dialog. "System UI isn't responding" is the system reporting that the app drawing your status bar has stopped responding, which is why the status bar freezes but the rest of the phone works.
  • The privacy indicators are SystemUI, reading app op state rather than a dedicated privacy signal.
  • Some "system" UI is not SystemUI. The power menu, the volume dialog and the recents gesture have moved between SystemUI, system_server and the launcher across releases.

Try it#

Find the SystemUI process

adb shell ps -A | grep systemui

Example output
u0_a123  1234  567  com.android.systemui
Dump its state

adb shell dumpsys activity service com.android.systemui/.SystemUIService | head -40

Example output
StatusBar: mState=1 mVisible=true
List installed tiles

adb shell dumpsys package | grep -i QS_TILE

Example output
com.example.app/.FocusTileService

Build it#

Write a TileService that toggles something real — a focus mode, a VPN, a Do Not Disturb state — and add it to Quick Settings. The interesting part is the lifecycle: the system binds the service when the shade opens and unbinds when it closes, so the tile must be able to render from persisted state without a network call.

Check yourself#

Check yourself

1 / 12

Put these notification features in the order they were introduced.

Drag, or use the arrows to reorder.

  1. 1Lock screen notifications and heads-up peeks
  2. 2POST_NOTIFICATIONS as a runtime permission
  3. 3Direct reply and bundled groups
  4. 4Expandable styles and actions
  5. 5Mandatory notification channels
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. docsNotifications overviewdeveloper.android.comaccessed 2026-10-27↩
  2. docsModular system componentssource.android.comaccessed 2026-10-27↩
  3. docsCreate and manage notification channelsdeveloper.android.comaccessed 2026-10-27↩
  4. docsPerubahan perilaku: aplikasi yang menargetkan API level 28+developer.android.comaccessed 2026-10-27↩
  5. docsBehavior changes: Apps targeting Android 14developer.android.comaccessed 2026-10-27↩