readme.md
1# SurfaceFlinger FrontEnd
2
3SurfaceFlinger FrontEnd implements the client APIs that describe how buffers should be
4composited on the screen. Layers are used to capture how the buffer should be composited
5and each buffer is associated with a Layer. Transactions contain an atomic set of changes
6to one or more of these layers. The FrontEnd consumes these transactions, maintains the
7layer lifecycle, and provides a snapshot to the composition engine every frame that
8describes how a set of buffers should be composited.
9
10
11
12## Layers
13Layers are used to describe how a buffer should be placed on the display relative to other
14buffers. They are represented as a hierarchy, similar to a scene graph. Child layers can
15inherit some properties from their parents, which allows higher-level system components to
16maintain policies at different levels without needing to understand the entire hierarchy.
17This allows control to be delegated to different parts of the system - such as SystemServer,
18SysUI and Apps.
19
20### Layer Drawing Order
21Layers are drawn based on an inorder traversal, treating relative parents as
22direct parents. Negative z-values place layers below their parent, while
23non-negative values place them above. Layers with the same z-value are drawn
24in creation order (newer on top). However, relying on creation order for
25z-ordering is discouraged; use unique z-values whenever possible for better
26control.
27
28Traversal pseudo code:
29```
30fn traverseBottomToTop(root):
31 for each child node including relative children,
32 sorted by z then layer id, with z less than 0:
33 traverseBottomToTop(childNode)
34
35 visit(root)
36
37 for each child node including relative children,
38 sorted by z then layer id, with z greater than
39 or equal to 0:
40 traverseBottomToTop(childNode)
41```
42
43### Layer Lifecycle
44Layer is created by a client. The client receives a strong binder reference to the layer
45handle, which will keep the layer alive as long as the client holds the reference. The
46layer can also be kept alive if the layer has a parent, since the parent will hold a
47strong reference to the children. If the layer is not reachable but its handle is alive,
48the layer will be offscreen and its resources will not be freed. Clients must explicitly
49release all references to the handle as soon as it's done with the layer. It's strongly
50recommended to explicitly release the layer in Java and not rely on the GC.
51
52
53
54## Transactions
55Transactions contain a group of changes to one or more layers that are applied together.
56Transactions can be merged to apply a set of changes atomically. Merges are associative,
57meaning how you group the merges does not matter, but they are not commutative, meaning
58that the order in which you merge them does.
59For example:
60
61`Transaction a; a.setAlpha(sc, 2);`
62
63`Transaction b; b.setAlpha(sc, 4);`
64
65`a.merge(b)` is not the same as `b.merge(a)`
66
67<p>
68
69`Transaction c; c.setAlpha(sc, 6);`
70
71`a.merge(b).merge(c)` is the same as `b.merge(c); a.merge(b);`
72
73Transactions are queued in SurfaceFlinger per ApplyToken so order is only guaranteed for
74Transactions with the same applyToken. By default each process and each buffer producer
75provides a unique ApplyToken. This prevents clients from affecting one another, and possibly
76slowing each other down.
77
78
79
80## Architecture
81SurfaceFlinger FrontEnd intends to optimize for predictability and performance because state
82generation is on the hotpath. Simple buffer updates should be as fast as possible, and they
83should be consistently fast. This means avoiding contention (e.g., locks) and context
84switching. We also want to avoid doing anything that does not contribute to putting a pixel
85on the display.
86
87The pipeline can be broken down into five stages:
88- Queue and filter transactions that are ready to be committed.
89- Handle layer lifecycles and update server-side state per layer.
90- Generate and/or update the traversal trees.
91- Generate a z-ordered list of snapshots.
92- Emit callbacks back to clients
93
94
95### TransactionHandler
96TransactionHandler is responsible for queuing and filtering transactions that are ready to
97be applied. On commit, we filter the transactions that are ready. We provide an interface
98for other components to apply their own filter to determine if a transaction is ready to be
99applied.
100
101
102### LayerLifecycleManager
103RequestedLayerState is a simple data class that stores the server side layer state.
104Transactions are merged into this state, similar to how transactions can be merged on the
105client side. The states can always be reconstructed from LayerCreationArgs and a list of
106transactions. LayerLifecycleManager keeps track of Layer handle lifecycle and the layer
107lifecycle itself. It consumes a list of transactions and generates a list of server side
108states and change flags. Other components can register to listen to layer lifecycles.
109
110
111### LayerHierarchyBuilder
112LayerHierarchyBuilder consumes a list of RequestedLayerStates to generate a LayerHierarchy.
113The hierarchy provides functions for breadth-first traversal and z-order traversal of the
114entire tree or a subtree. Internally, the hierarchy is represented by a graph. Mirrored
115layers are represented by the same node in the graph with multiple parents. This allows us
116to implement mirroring without cloning Layers and maintaining complex hierarchies.
117
118
119### LayerSnapshotBuilder
120LayerSnapshotBuilder consumes a LayerHierarchy along with a list of RequestedLayerStates to
121generate a flattened z-ordered list of LayerSnapshots. LayerSnapshots contain all the data
122required for CompositionEngine and RenderEngine. It has no dependencies to FrontEnd, or the
123LayerHierarchy used to create them. They can be cloned and consumed freely. Other consumers
124like WindowInfo listeners (input and accessibility) also updated from these snapshots.
125
126Change flags are used to efficiently traverse this hierarchy where possible. This allows us
127to support short circuiting parts of the hierarchy, partial hierarchy updates and fast paths
128for buffer updates.
129
130
131While they can be cloned, the current implementation moves the snapshot from FrontEnd to
132CompositionEngine to avoid needless work in the hotpath. For snapshot consumers not critical
133to composition, the goal is to clone the snapshots and consume them on a background thread.
134