上一篇文章介绍了整个Surface机制(我是这么称呼的,主要是Surface的建立,Surface的显示存储的管理),同时我们也介绍过了整个显示系统,那么这篇文章就介绍一下SurfaceFlinger 这个核心服务层的机制。
从代码中我们可以看出SurfaceFlinger 是一个thread,运行在system_server进程中,并且其threadLoop()方法的返回值为true,因此它是一个循环的loop。这样保证了SurfaceFlinger业务的循环周期性。
首先,先来个综述,下图是我总结的一个SurfaceFlinger结构的概括图:
1. SurfaceFlinger的同步
SurfaceFlinger 并不是时时刻刻都在执行业务中,当WMS请求SurfaceFlinger创建Surface,或者WMS对Surface进行属性设置时,我们希望此时的SurfaceFlinger并不进行显示操作,以保证对Surface的线程保护,因此SurfaceFlinger 的loop中实现了同步机制。
waitForEvent();
主要的同步情况有如下几种,当然也有其他一些要求SurfaceFlinger同步的情况,不够对于研究SurfaceFlinger就不太重要了
1. 创建Surface同步
假如当前只有一个Client,比如WMS请求SufaceFlinger创建一个Surface,那么此时应该保持SurfaceFlinger loop处在block状态,因为这个过程涉及到对一些成员变量的处理,为了保证同步而需要hold住整个loop。
2. 设置Surface属性或SurfaceFlinger属性同步
创建完Surface之后,WMS会请求SurfaceFlinger对其Layer进行属性设置或者对SurfaceFlinger的属性进行设置,如上面概括图中SurfaceComposerClient中的函数接口。
3. Surface绘制同步
当ViewRoot对Surface进行绘制时,同样需要将SurfaceFlinger hold住,当整个窗口绘制完成之后,再向SurfaceFlinger发送signal信号。如下面时序图所示。
4. freeze/unfreeze同步
当每个Activity启动的时候,AMS都会请求WMS freeze整个屏幕,当Activity启动之后,再unfreeze整个屏幕,我猜测这么做的目的是为了保证在Activity以及Activity的窗口在创建过程中,对Activity窗口的Surface进行的线程保护,以免出现屏幕的闪烁等用户体验较差的现象。
2. Layer存储
在SurfaceFlinger中,Layer是怎么样存储的呢?所有的Layer,不论是那个Client创建的Layer,均保存在一个名为layersSortedByZ的变量中,也就是说WMS请求创建的Surface的Layer和其他Client请求创建的Layer都保存在layersSortedByZ中,但是layersSortedByZ保存过程中则遵守一定的规则。下面代码中的do_compare揭示了这个规则。
@SurfaceFlinger.h
class LayerVector : public SortedVector< sp<LayerBase> > {
public:
LayerVector() { }
LayerVector(const LayerVector& rhs) : SortedVector< sp<LayerBase> >(rhs) { }
virtual int do_compare(const void* lhs, const void* rhs) const {
const sp<LayerBase>& l(*reinterpret_cast<const sp<LayerBase>*>(lhs));
const sp<LayerBase>& r(*reinterpret_cast<const sp<LayerBase>*>(rhs));
// sort layers by Z order
uint32_t lz = l->currentState().z;
uint32_t rz = r->currentState().z;
// then by sequence, so we get a stable ordering
return (lz != rz) ? (lz - rz) : (l->sequence - r->sequence);
}
};
每次向
layersSortedByZ中添加新的Layer,都会做一次排序,按照规则将其放在合适的位置。
1. 首先,按照Layer的Z-order值来排序,Z-order值小的,放在layersSortedByZ低索引值位置;
2. 其次,如果两个Layer Z-order值相同,sequence值小的,放在layersSortedByZ低索引值位置;
Z-order值如何确定?
WMS根据不同的Window Type来确定Z-order值,Z-order = LAYER*TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET。
根据下面代码中的不同的Window Type的LAYER值,可以确定Z-order值,例如TYPE_APPLICATION窗口,其
Z-order = 2*10000+1000 = 21000。
@PhoneWindowManager.java
// wallpaper is at the bottom, though the window manager may move it.
static final int WALLPAPER_LAYER = 2;
static final int APPLICATION_LAYER = 2;
static final int PHONE_LAYER = 3;
static final int SEARCH_BAR_LAYER = 4;
static final int STATUS_BAR_PANEL_LAYER = 5;
static final int SYSTEM_DIALOG_LAYER = 6;
// toasts and the plugged-in battery thing