constsp&layer=currentLayers[i];
uint32_ttrFlags=layer->getTransactionFlags(eTransactionNeeded);
if(!
trFlags)continue;
constuint32_tflags=layer->doTransaction(0);
if(flags&Layer:
:
eVisibleRegion)
mVisibleRegionsDirty=true;
}
}
这段代码用来处理应用程序窗口的属性变化。
参数transactionFlags最开始是从SurfaceFlinger类的成员函数threadLoop传进来的。
从前面一文可以知道,SurfaceFlinger类的成员函数threadLoop在调用另外一个成员函数handleTransaction来处理系统显示屏以及应用程序窗口的属性变化之前,首先会调用成员函数getTransactionFlags来检查系统显示屏或者应用程序窗口的属性是否发生了变化。
如果系统显示屏的属性发生了变化,那么传到这里的参数transactionFlags的eTransactionNeeded位就会等于1,而如果有应用程序窗口的属性发生了变化,那么传到这里的参数transactionFlags的eTraversalNeeded位就会等于1。
为了方便描述,我们假设系统显示屏以及应用程序窗口的属性都发生了变化。
SurfaceFlinger类的成员变量mCurrentState指向了一个State对象,用来描述SufaceFlinger服务的当前状态,其中,这个State对象的成员变量layersSortedByZ是一个类型为LayerVector的向量,它里面保存了SufaceFlinger服务当前所需要渲染的应用程序窗口,而这些应用程序窗口都是使用一个LayerBase对象来描述的。
这段代码首先获得SufaceFlinger服务当前所需要渲染的应用程序窗口,接着再通过一个for循环来依次检查每一个应用程序窗口的属性是否发生了变化。
如果某一个应用程序窗口的属性被修改过,那么调用用来描述这个应用程序窗口的一个LayerBase对象的成员函数getTransactionFlags得到的返回值trFlags就不会等于0,在这种情况下,这段代码就会调用这个LayerBase对象的成员函数doTransaction来处理对应的应用程序窗口的属性变化。
在LayerBase类中,有一个类型为int32_t的成员变量mTransactionFlags,每当SurfaceFlinger服务修改某一个应用程序窗口的属性时,都会将与其对应的LayerBase的成员变量mTransactionFlags的相应的位设置为1,这样LayerBase类的成员函数getTransactionFlags就可以通过这个成员变量来判断一个应用程序窗口的属性是否发生变化了。
如果一个应用程序窗口发生的属性变化是可见区域发生了改变,那么对应的LayerBase对象的成员函数doTransaction的返回值flags的Layer:
:
eVisibleRegion位就会等于1。
在这种情况下,这段代码就会将SurfaceFlinger类的成员变量mVisibleRegionsDirty的值设置为true,表示后面要重新计算各个应用程序窗口的可见区域。
为了方便描述,我们假设发生了属性变化的应用程序窗口是一个普通类型的Surface,即用来描述它的实际是一个从LayerBase类继承下来的Layer对象。
在这种情况下,前面实际上调用了Layer类的成员函数doTransaction来处理一个应用程序窗口的属性变化。
在接下来的Step3中,我们再详细分析Layer类的成员函数doTransaction的实现,现在我们接着往下阅读SurfaceFlinger类的成员函数handleTransactionLocked的代码:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
/*
*Performourowntransactionifneeded
*/
if(transactionFlags&eTransactionNeeded){
if(mCurrentState.orientation!
=mDrawingState.orientation){
//theorientationhaschanged,recomputeallvisibleregions
//andinvalidateeverything.
constintdpy=0;
constintorientation=mCurrentState.orientation;
constuint32_ttype=mCurrentState.orientationType;
GraphicPlane&plane(graphicPlane(dpy));
plane.setOrientation(orientation);
//updatethesharedcontrolblock
constDisplayHardware&hw(plane.displayHardware());
volatiledisplay_cblk_t*dcblk=mServerCblk->displays+dpy;
dcblk->orientation=orientation;
dcblk->w=plane.getWidth();
dcblk->h=plane.getHeight();
mVisibleRegionsDirty=true;
mDirtyRegion.set(hw.bounds());
}
if(mCurrentState.freezeDisplay!
=mDrawingState.freezeDisplay){
//freezingorunfreezingthedisplay->triggeranimationifneeded
mFreezeDisplay=mCurrentState.freezeDisplay;
if(mFreezeDisplay)
mFreezeDisplayTime=0;
}
if(currentLayers.size()>mDrawingState.layersSortedByZ.size()){
//layershavebeenadded
mVisibleRegionsDirty=true;
}
//somelayersmighthavebeenremoved,so
//weneedtoupdatetheregionsthey'reexposing.
if(mLayersRemoved){
mLayersRemoved=false;
mVisibleRegionsDirty=true;
constLayerVector&previousLayers(mDrawingState.layersSortedByZ);
constsize_tcount=previousLayers.size();
for(size_ti=0;iconstsp&layer(previousLayers[i]);
if(currentLayers.indexOf(layer)<0){
//thislayerisnotvisibleanymore
ditchedLayers.add(layer);
mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
}
}
}
}
这段代码用来处理系统显示屏的属性变化。
在分析这段代码之前,我们首先了解SurfaceFlinger类的另外一个成员变量mDrawingState的含义。
SurfaceFlinger类的成员变量mDrawingState与前面所介绍的成员变量mCurrentState类似,它的类型也为State,不过它是用来描述SufaceFlinger服务的上一次渲染状态的。
通过这两个成员变量的比较,我们就可以知道系统显示屏的哪一个属性发生了变化。
前面提到,当系统显示屏的属性发生了变化,那么参数transactionFlags的eTransactionNeeded位就会等于1,在这种情况,这段代码就需要完成四件事情。
第一件事情是判断系统显示屏的旋转方向是否发生变化。
State类的成员变量orientation用来描述显示屏的方向,因此,当SurfaceFlinger类的成员变量mCurrentState所描述的一个State对象的成员变量orientation的值不等于SurfaceFlinger类的成员变量mDrawingState所描述的一个State对象的成员变量orientation的值时,就说明系统显示屏的旋转方向发生了变化。
在这种情况下,我们就需要将系统显示屏的旋转方向设置为SurfaceFlinger类的成员变量mCurrentState所描述的一个State对象的成员变量orientation的值,这是通过调用编号为0的一个GraphicPlane对象的成员函数setOrientation来实现的。
SurfaceFlinger服务的UI渲染线程在初始化的过程中,除了会初始化硬件帧缓冲区之外,还会创建一个类型为surface_flinger_cblk_t的对象,用来描述系统显示屏的信息,例如大小和旋转方向等,以便其它进程可以通过这个surface_flinger_cblk_t对象来获得系统显示屏的信息。
这个surface_flinger_cblk_t对象就保存在SurfaceFlinger类的成员变量mServerCblk中。
因此,当系统显示屏的旋转方向发生了变化时,我们还需要将变化后的旋转方向保存在SurfaceFlinger类的成员变量mServerCblk所描述的一个surface_flinger_cblk_t对象中。
由于系统显示屏的旋转方向变化一般意味着宽度和高度也会发生变化,因此,我们还需要将旋转发生变化后得到的系统显示屏的宽度和高度值保存在SurfaceFlinger类的成员变量mServerCblk所描述的一个surface_flinger_cblk_t对象中。
系统显示屏的旋转方向同时也意味着我们需要重新计算各个应用程序窗口的可见区域以及重新绘制整个显示屏,因此,在这种情况下,我们还需要将SurfaceFlinger类的成员变量mVisibleRegionsDirty的值设置为true,以及将SurfaceFlinger类的成员变量mDirtyRegion的大小设置为整个显示屏的大小,即将系统UI的脏区域设置为整个显示屏的大小。
第二件事情是判断系统显示屏的冻结状态是否发生变化。
State类的成员变量freezeDisplay用来描述显示屏的冻结状态,因此,当SurfaceFlinger类的成员变量mCurrentState所描述的一个State对象的成员变量freezeDisplay的值不等于SurfaceFlinger类的成员变量mDrawingState所描述的一个State对象的成员变量freezeDisplay的值时,就说明系统显示屏的冻结状态发生了变化。
在这种情况下,我们就需要将SurfaceFlinger类的成员变量mFreezeDisplay的值设置为SurfaceFlinger类的成员变量mCurrentState所描述的一个State对象的成员变量freezeDisplay的值。
如果显示屏的是由解冻状态变化为冻结状态的,那么还需要将显示屏的冻结时间设置为0,即将SurfaceFlinger类的成员变量mFreezeDisplayTime的值设置为0,以便可以将显示屏进入到冻结状态的最长时间设置为一个默认值,这一点可以参考前面一文。
第三件事情是判断是否新增了应用程序窗口。
State类的成员变量layersSortedByZ是一个类型LayerVector的向量,里面保存的是SurfaceFlinger服务在某一个状态下所拥有的应用程序窗口,因此,当SurfaceFlinger类的成员变量mCurrentState所描述的一个State对象的成员变量layersSortedByZ所指向的一个向量的大小值大于SurfaceFlinger类的成员变量mDrawingState所描述的一个State对象的成员变量layersSortedByZ所指向的一个向量的大小值时,就说明系统新增了应用程序窗口。
在这种情况下,我们就需要将SurfaceFlinger类的成员变量mVisibleRegionsDirty的值设置为true,以表示我们需要重新计算各个应用程序窗口的可见区域。
第四件事情是判断是否移除了某些应用程序窗口。
SurfaceFlinger类的成员变量mLayersRemoved用来描述是否有应用程序窗口被移除了。
如果有有应用程序窗口被移除的话,那么这个成员变量的值就会等于true。
在这种情况下,我们就需要是哪些应用程序窗口被移除了。
计算的方法很简单,如果一个应用程序窗口存在于SurfaceFlinger类的成员变量mDrawingState所描述的一个State对象的成员变量layersSortedByZ所指向的一个向量中,但是不存在于SurfaceFlinger类的成员变量mCurrentState所描述的一个State对象的成员变量layersSortedByZ所指向的一个向量中,那么就说明这个应用程序窗口被移除了,因此,就需要将它保存输出参数ditchedLayers所描述的一个向量中,以便可以返回给上一步来处理。
SurfaceFlinger类的成员变量mDirtyRegionRemovedLayer用来描述那些被移除了的应用程序窗口所占用的区域,因此,每当我们移除一个应用程序窗口的时候,都需要将它所占用的区域增加到SurfaceFlinger类的成员变量mDirtyRegionRemovedLayer所描述的一个区域去。
当处理完成那些被移除的应用程序窗口之后,我们就需要将SurfaceFlinger类的成员变量mLayersRemoved的值设置为false,并且将SurfaceFlinger类的成员变量mVisibleRegionsDirty的值设置为true,以表示我们需要重新计算现存的各个应用程序窗口的可见区域。
处理完成系统显示屏的属性变化之后,我们接着向下阅读SurfaceFlinger类的成员函数handleTransactionLocked的最后一行代码: