Zygote
Input & windowsintermediate

Windows and WindowManager

Windows are the unit of z-order, focus and input routing. WindowManager decides where they go, what they contain, and which one gets the touch — and the answer is not always the one on top.

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

An Activity feels like a screen, and a window feels like a rectangle. In the system's model it is the reverse: the window is the object that owns a rectangle on the display, and the Activity merely asks for one. Understanding that inversion explains z-order, focus, insets, dialogs and the "app is behind the keyboard" problem.

TL;DR#

  • A window is the unit of display surface, input routing and z-order. An Activity has at least one.
  • WindowManagerService (in system_server) owns the window list, the layers and the focus.
  • A window has a type that places it in a layer band, and a token that ties it to an Activity or an app.
  • Focus is not the same as topmost: a window can be visible and not focusable, or focusable and not touchable in parts.
  • The Shell (WMShell) implements the window-management UI — the recents gesture, split screen — outside system_server.

Mental model#

Think of a theatre stage with a fly system.

Each window is a flat scenery panel. Panels are hung in a fixed order, and each has a track it slides along.

The fly operator is WindowManagerService: it decides which panels are down, in what order, and how big they are.

The lighting is SurfaceFlinger: it illuminates whatever panels are down.

The usher is InputDispatcher: when someone in the audience points at the stage, the usher works out which panel they are pointing at — which is not necessarily the frontmost one, if that panel is transparent to touch.

Where the analogy breaks#

Panels do not move relative to the audience or change size; windows do, constantly, and often during an animation. A window's frame, crop, alpha and layer can all change in a single transaction. And a window can exist without being visible at all — created, measured and laid out but not yet shown, which is how an Activity prepares its first frame.

The big picture#

Loading diagram…
Text description of this diagram

The window stack from bottom to top: wallpaper, app base windows, a dialog, the IME, the status and navigation bars, and a toast. Each window has a type; the type determines a band, and the band determines z-order and which window is asked first for input. The diagram shows that the keyboard is an ordinary window from another app, and that a toast is above everything but never receives touch.

The bands in that diagram are the reason a dialog from app A can appear above app B's window, and the reason the keyboard covers your content rather than the other way around.

Deep dive#

Windows are objects, Activities are clients#

WindowManagerService holds a list of WindowState objects.1 Each has a frame, a layer, a visibility state, an input channel and a token.

An Activity gets a window through Window (usually PhoneWindow), and the window's DecorView is the root of the view hierarchy. When you call setContentView, you are populating the content view inside that window.

// Every Activity already has a window; this is the object behind it.
window.setLayout(
    WindowManager.LayoutParams.MATCH_PARENT,
    WindowManager.LayoutParams.WRAP_CONTENT
)

Types and layer bands#

Each window has a WindowManager.LayoutParams.type. The type is not arbitrary: it selects a band, and the band selects a z-order range.

BandTypical typesOwner
WallpaperTYPE_WALLPAPERSystemUI / wallpaper service
ApplicationTYPE_BASE_APPLICATION, TYPE_APPLICATIONany app
Sub-windowTYPE_APPLICATION_ATTACHED_DIALOG, TYPE_APPLICATION_PANELan app, attached to a parent
IMETYPE_INPUT_METHODthe current input method
SystemTYPE_STATUS_BAR, TYPE_NAVIGATION_BARSystemUI
TopTYPE_TOAST, overlaysany app with permission

Apps cannot normally create system-band windows; TYPE_APPLICATION_OVERLAY requires the draw-over-apps permission and is placed below the system bars. That restriction exists because a window above the status bar could spoof it.

Tokens: what a window belongs to#

A window carries a token that identifies its owner — an Activity token, or an application token for windows that are not tied to an Activity.2 The token is what makes these work:

  • Dialogs. A dialog window attached to an Activity's token moves with the Activity, is dismissed with it, and is placed above it.
  • Focus. The system can move focus to the correct window when the Activity comes forward, because it knows which windows belong to it.
  • Security. A window without the right token cannot be placed above another app's window.

Focus versus touchability#

These are three separate properties:

  • Visible: the window is drawn.
  • Focusable: the window can receive key events.
  • Touchable: the window can receive touch events, within its touchable region.

A toast is visible and neither focusable nor touchable. A status bar is visible, not focusable, and touchable only in parts. A dialog is all three. The FLAG_NOT_FOCUSABLE and FLAG_NOT_TOUCHABLE flags control the latter two.

WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL is the one that most often surprises: without it, a non-fullscreen window blocks touches to everything behind it even outside its own bounds. With it, touches outside its frame go to the window below.

Insets: the window's obligations#

A window does not own the whole display. The system bars, the cutout and the IME reserve space, and the window is told about that space through insets. Whether the window is laid out inside those bounds or behind them is a choice — one that changed by default in recent releases. See Insets and edge-to-edge.

The Shell#

The window-management policy is no longer all in system_server. The Shell (WMShell) is a separate process that implements the interactive parts3: the recents gesture, split-screen and freeform transitions, and the transition animations. It talks to WindowManagerService through a stable interface rather than living inside it.

That split is why the recents animation can be updated independently of the platform, and why a Shell crash does not take down window management itself.

Transitions#

A transition is a coordinated animation between window states: app A fading out while app B fades in, or a window resizing while its contents reflow. The Transitions infrastructure in system_server coordinates the animation, collecting the participating windows and running the animation as a single transaction so no intermediate state is shown.

This is the mechanism that makes a "shared element" transition look continuous: the system knows both windows and animates their surfaces together, rather than the app animating one and the system cutting to the other.

Why focus is a system decision, not an app one#

An app cannot simply take focus. It requests it — through requestFocus, or implicitly by showing a focusable window — and WindowManagerService decides whether the request wins.

The decision uses the window's type, its layer, whether it is focusable and whether it is visible. A window that is not focusable never takes focus, regardless of what the app asks. That is why a FLAG_NOT_FOCUSABLE overlay cannot steal the keyboard from the app beneath it, and why the rule is enforced centrally rather than by convention.

The window's insets are the window's obligations#

A window is told what the system reserves around it. A full-screen app gets a content inset for the status and navigation bars; a floating window may get none, because it does not overlap them.

The framework applies these insets to the window's layout by default. Whether it does is a property of the window's LayoutParams, which is why an app that sets FLAG_LAYOUT_NO_LIMITS gets a window extending under everything — and why that flag is almost always a mistake.

Transitions are transactions with a clock#

A transition is not only an animation; it is a coordinated state change. The Transitions infrastructure in system_server collects the participating windows, snapshots their start and end states, and runs an animation that is applied as a sequence of transactions.

That is why the animation is smooth even when the app is not drawing: the system is animating the window's geometry and alpha, not the app's content. The app's buffer is scaled or faded as a whole.

When an app participates in a transition — a shared element, a custom animation — it registers a participant and supplies start and end values. The system still owns the clock.

What the app can and cannot control#

The app canThe app cannot
choose its window type (within limits)place a window above a system window
set flags for focus and touchabilitydecide which window is topmost
request a size and position (within policy)override the Shell's split-screen layout
provide transition participantschange the transition's timing curve

The pattern is consistent: the app describes intent, and the system applies policy. That is what makes one app's window behaviour predictable in the presence of every other app.

Why dumpsys window is the first tool#

Almost every window question — why is this on top, why is the keyboard covering it, why is the touch going to the wrong place — is answered by reading the window list. dumpsys window windows shows the type, frame, visibility and focus state of each window, and dumpsys input shows which window the dispatcher believes has focus.

Before writing code to work around a window problem, read the list. The system's view of the world is usually correct, and the app's assumption is usually what is wrong.

How it evolved#

API 1–API 10One windowone full-screen window at a timeAPI 1
API 11 →Fragments and dialogsmore windows per screenAPI 11
API 24 →Multi-windowtwo apps share the displayAPI 24
API 32 →Shell and desktop windowswindow policy moves out of system_serverAPI 32
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#

Curiosity corner#

  • The status bar is an app. SystemUI owns it as an ordinary window with a system type, which is why it can crash and restart without taking the rest of the system with it.
  • A window can be bigger than the screen. Freeform and desktop windowing allow windows that extend beyond the display bounds; the visible region is cropped, not resized.
  • The navigation bar can be a window or a gesture region, depending on the navigation mode — the same band, a different input story.

Try it#

All windows with focus
adb shell dumpsys window windows | grep -E "Window #|mFrame|mHasSurface"
Example output
Window #0 Window{9c1f3a u0 com.example.app/com.example.app.MainActivity}:
mDisplayId=0 mFrame=[0,0][1080,2400] mHasSurface=true
mViewVisibility=0x0 mPolicyVisibility=true
Window #1 Window{4b2d11 u0 StatusBar}:
mFrame=[0,0][1080,96] mHasSurface=true
The current focus
adb shell dumpsys window | grep -E "mCurrentFocus|mFocusedApp"
Example output
mCurrentFocus=Window{9c1f3a u0 com.example.app/com.example.app.MainActivity}
mFocusedApp=ActivityRecord{...}
Window size and insets
adb shell dumpsys window | grep -A5 "mFrame"
Example output
mFrame=[0,0][1080,2400]
mContentInsets=Insets{left=0, top=96, right=0, bottom=132}

Check yourself#

Check yourself

1 / 12

Why does the system deliver input to an app through a socket pair rather than a Binder call?

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. docsSurfaceFlinger and WindowManagersource.android.comaccessed 2026-10-27↩
  2. docsLayers and displayssource.android.comaccessed 2026-10-27↩
  3. docsLarge screens overviewdeveloper.android.comaccessed 2026-10-27↩
  4. docsInput overviewsource.android.comaccessed 2026-10-27↩
  5. docsWinscopesource.android.comaccessed 2026-10-27↩
  6. docsBehavior changes: Apps targeting Android 12developer.android.comaccessed 2026-10-27↩