Android 系统的显示依赖于 SurfaceFlinger 对图层的合成,想要获得正确的显示效果,SurfaceFlinger 必须要正确处理图层。然而,图层处于不断地变化中,所以 SurfaceFlinger 需要不断获取和更新图层的信息。如何表示图层的状态、如何获取图层的状态、如何消费图层的状态等问题就成了 SurfaceFlinger 合成流程中重要的一环。
一、图层状态的概念
图层状态 (Layer State) 指的是用于描述 android::Layer 状态的结构体 State,在最初的 AOSP 版本中,它的定义如下:
// [frameworks/native/libs/surfaceflinger/LayerBase.h]
struct State {
uint32_t w;
uint32_t h;
uint32_t z;
uint8_t alpha;
uint8_t flags;
uint8_t reserved[2];
uint32_t sequence; // changes when visible regions can change
uint32_t tint;
Transform transform;
Region transparentRegion;
};
随着 Android 版本的变动,图层状态包含的信息也在频繁变动。但是,图层状态的核心功能始终保持一致——存储图层的状态信息,以供合成引擎使用。
二、图层状态的使用逻辑
从上一节的概念中可以看到。图层状态是定义在图层中的一个内部结构体,所以只在图层类中有图层状态类型的成员变量。仍以最初的 AOSP 版本为例:
class LayerBase
{
// ...
// these are protected by an external lock
State mCurrentState;
State mDrawingState;
// ...
};
此时,在图层中定义有两个 State 变量:mCurrentState 和 mDrawingState。
2.1 mCurrentState 的概念和用法
mCurrentState 表示图层当前的状态,对图层进行更新时直接操作的是 mCurrentState,使用前需要获得外部锁的保护。
更新 mCurrentState 的逻辑分两种。一种是在创建图层时,把构造函数中的参数赋值给 mCurrentState:
void LayerBase::initStates(uint32_t w, uint32_t h, uint32_t flags)
{
// ...
mCurrentState.z = 0;
mCurrentState.w = w;
mCurrentState.h = h;
mCurrentState.alpha = 0xFF;
mCurrentState.flags = layerFlags;
mCurrentState.sequence = 0;
mCurrentState.transform.set(0, 0);
// ...
}
另一种是在各类 set 函数中,将传入的参数赋值给 mCurrentState 的对应变量。下面以 setPosition 函数为例:
bool LayerBase::setPosition(uint32_t x, uint32_t y)
{
// ...
mCurrentState.sequence++;
mCurrentState.transform.set(x, y);
// ...
}
2.2 mDrawingState 的概念和用法
mDrawingState 表示图层绘制时的状态,SurfaceFlinger 会把 mDrawingState 中的信息提交给合成引擎使用。图层不会直接更新 mDrawingState 中的变量,而是通过将 mCurrentState 赋值给 mDrawingState 实现间接更新。更新 mDrawingState 的逻辑也有两处,一处在 initStates 函数中,另一处在 commitTransaction 函数中。
void LayerBase::initStates(uint32_t w, uint32_t h, uint32_t flags)
{
// ...
// drawing state & current state are identical
mDrawingState = mCurrentState;
}
void LayerBase::commitTransaction(bool skipSize)
{
// ...
mDrawingState = mCurrentState;
// ...
}
2.3 SurfaceFlinger 如何使用图层状态
Step 1: SurfaceFlinger 在 createNormalSurfaceLocked 函数中创建 Layer,Layer 初始化时也会初始化 mCurrentState 和 mDrawingState。
LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked(
Client* client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
{
// ...
Layer* layer = new Layer(this, display, client, id);
// ...
}
Step 2: SurfaceFlinger 在 setClientState 函数中根据客户端状态去更新对应图层的状态。仍以 setPosition 相关逻辑为例:
status_t SurfaceFlinger::setClientState(
ClientID cid, int32_t count,
const layer_state_t* state)
{
// ...
for (int i=0; i<count; i++) {
const layer_state_t& s = state[i];
LayerBaseClient* layer = getLayerUser_l(s.surface | cid);
if (layer) {
const uint32_t what = s.what;
// ...
if (what & ePositionChanged) {
if (layer->setPosition(s.x, s.y))
flags |= eTraversalNeeded;
}
// ...
}
}
// ...
}
Step 3: SurfaceFlinger 在 handleTransaction 函数中对每个图层调用 Layer::doTransaction,实现将 mCurrentState 赋值给 mDrawingState。
// [frameworks/native/libs/surfaceflinger/SurfaceFlinger.cpp]
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
// ...
const bool layersNeedTransaction = transactionFlags & eTraversalNeeded;
if (layersNeedTransaction) {
for (size_t i=0; i<count; i++) {
LayerBase* const layer = currentLayers[i];
// ...
const uint32_t flags = layer->doTransaction(0);
// ...
}
}
// ...
}
// [frameworks/native/libs/surfaceflinger/Layer.cpp]
void Layer::doTransaction(uint32_t flags)
{
// ...
return LayerBase::commitTransaction(flags);
}
// [frameworks/native/libs/surfaceflinger/LayerBase.cpp]
void LayerBase::commitTransaction(bool skipSize)
{
// ...
mDrawingState = mCurrentState;
// ...
}
Step 4: 当 SurfaceFlinger 进行合成时,在 computeVisibleRegions 函数中会获取每个图层的 mDrawingState,并根据其中的状态信息计算可见区域。
void SurfaceFlinger::computeVisibleRegion(uint32_t transactionFlags)
{
// ...
while (i--) {
LayerBase* const layer = currentLayers[i];
layer->vilidateVisibility(planeTransform);
// start with the whole surface at its current location
const Layer::State& s = layer->drawingState();
const Rect bounds(layer->visibleBounds());
// ...
}
// ...
}
三、图层状态变动史
笔者是从 Android 11 才开始接触 Android,所以仅分析 Android 11 及之后的版本。
3.1 Android 11
相较于最初的 Android 版本, Android 11 的代码结构发生了很大的变化,但是图层状态的核心逻辑没有变动。在 Android 11 中,Google 已经移除了 LayerBase 类,相关逻辑被整合进了 Layer 中。
class Layer : public virtual RefBase, compositionengine::LayerFE {
// ...
// These are only accessed by the main thread or the tracing thread
State mDrawingState;
// these are protected by an external lock (mStateLock)
State mCurrentState;
// ...
};
整体逻辑和 2.3 节一致,只是具体的实现形式有差异。
3.2 Android 12
Android 12 移除了 mCurrentState,因为保证只在主线程中写当前状态,所以可以直接写绘制状态,这样就避免了每一帧提交事务时要将 mCurrentState 拷贝给 mDrawingState。根据 Google 对弹跳球用例的 simpleperf 测试,每帧可以节省大约 8% 的 CPU。详细信息参阅:
3.3 Android 14
3.3.1 新的 SurfaceFlinger 前端
Android 14 引入了 SurfaceFlinger 前端 以实现客户端接口,这些接口描述了缓冲区如何在屏幕上进行合成。
- 图层 (Layer) 用于定义缓冲区如何合成,每个缓存区与一个图层相关联
- 事务 (Transaction) 包含了一个或一组图层原子变化的集合
- 快照 (LayerSnapshot) 用于描述一组缓冲区应该如何合成,它包含合成引擎和渲染引擎需要的所有数据
SurfaceFlinger 前端消费事务,维持图层的生命状态,在每一帧时给合成引擎提供一个快照,以描述一组缓冲区应该如何进行合成。
3.3.2 SurfaceFlinger 前端的工作流程
SurfaceFlinger 前端包含如下五个流程:
- 队列化和过滤待提交的事务
- 处理图层的生命周期并更新每个图层服务侧的状态
- 生成和/或更新遍历树
- 生成一个 z 排序的快照列表
- 发送回调给客户端
3.3.3 SurfaceFlinger 前端的设计目的
根据 Google 的文档, SurfaceFlinger 前端旨在优化可预测性和性能,因为状态的生成处于 关键路径 上。简单的缓冲区更新应该处于 快速路径 上,并且速度应始终很快。当进入快速路径时,SurfaceFlinger 无需生成一棵完整的遍历树,而只需要对遍历树进行更新,从而减少了这一帧的 CPU 开销。为了实现这一功能,SurfaceFlinger 前端引入了 LayerLifecycleManager 和 LayerSnapshotBuilder 等数据结构协助判断:
bool LayerSnapshotBuilder::tryFastUpdate(const Args& args)
{
if (args.forceUpdate != ForceUpdateFlags::None || args.displayChanges) {
// force update requested, or we have display changes, so skip the fast path
return false;
}
if (args.layerLifecycleManager.getGlobalChanges().get() == 0) {
return true;
}
if (args.layerLifecycleManager.getGlobalChanges().get() != RequestedLayerState::Changes::Content) {
// we have changes that require us to walk the hierarchy and update child layers
// No fast path for you.
return false;
}
// ...
return true;
}
详细信息参阅:
- 04f8969172df975a30d6975a159bd2880a4003af - platform/frameworks/native - Git at Google
- 8fc721bb338c6d13e8758c2139d073acab86e3e2 - platform/frameworks/native - Git at Google
3.4 Android 15
Android 15 正式启用了新的 SurfaceFlinger 前端。详细信息参阅 bdf565b2b74ef70f167e4855699ce947ffofa6d7 - platform/frameworks/native - Git at Google。
3.5 Android 16
在即将到来的 Android 16上,Google 正式移除了遗留的 SF 标志、图层操作逻辑和图层状态等逻辑。详细信息参阅 dc83d4b7ba27a5096e19884b548eb05e432bc3f2 - platform/frameworks/native - Git at Google。
四、总结
四、总结
从图层状态的变动史上可以看出 Google 这些年对 Android 性能的不断优化,包括减少拷贝调用、优化传递数据量、优化可预测性等。Google 对图层状态的改动和优化提供了一个范本,可以启发各位安卓开发者实际业务工作中的性能优化思路。
最后,从 Android 11 到 Android 16,完整的图层状态的变动史如下图所示: