Unsignaled buffer latching with AutoSingleLayer

Android 13 introduces a new configuration called AutoSingleLayer for latching unsignaled buffers. This configuration lets SurfaceFlinger latch an unsignaled buffer when only a single layer is updating. It does not apply to cases that occur across layers, for example, geometry changes or sync transactions.

Previously, the debug.sf.latch_unsignaled flag in the Android Open Source Project (AOSP) let SurfaceFlinger latch all unsignaled buffers, regardless of the use case. When you enable this configuration, it can cause undesired side effects, for example, breaking sync transactions and freezing the entire display while waiting on incomplete buffers.

In AutoSingleLayer mode, SurfaceFlinger updates only a buffer of a single surface in a frame. This mode lets games and other fullscreen apps benefit from latching unsignaled buffers and reducing app jank while remaining unaffected by display freezes.

AutoSingleLayer mode settings

For Android 13, AutoSingleLayer is the default mode for the latch unsignaled buffer feature. This mode is controlled by the system property debug.sf.auto_latch_unsignaled.

SurfaceFlinger reads LatchUnsignaledConfig on boot. The possible configurations are:

  • LatchUnsignaledConfig::AutoSingleLayer

    In this AOSP default mode, SurfaceFlinger permits latching unsignaled buffers when a single layer updates in a frame. The update must include only a buffer update with no sync transactions or geometry changes. By default, this mode sets debug.sf.auto_latch_unsignaled to true.

  • LatchUnsignaledConfig::Disabled

    This mode disables the latch unsignaled behavior and latches only signaled transactions. This mode also disables AutoSingleLayer mode. To configure this mode, set debug.sf.latch_unsignaled and debug.sf.auto_latch_unsignaled to false.

  • LatchUnsignaledConfig::Always

    In this mode, SurfaceFlinger latches all buffers unsignaled. To configure this mode, set debug.sf.latch_unsignaled to true.

Test AutoSingleLayer

To test whether a buffer is latched unsignaled, look for the following traces from SurfaceFlinger in Perfetto:

Trace of latched unsignaled buffer

Figure 1. Trace of a latched unsignaled buffer in Perfetto