8.5.3 Transaction分析
Transaction是“事务”的意思。在我脑海中,关于事务的知识来自数据库。在数据库操作中,事务意味着一次可以提交多个SQL语句,然后一个commit就可让它们集中执行,而且数据库中的事务还可以回滚,即恢复到事务提交前的状态。
SurfaceFlinger为什么需要事务呢?从上面对数据库事务的描述来看,是不是意味着一次执行多个请求呢?如直接盯着SF的源码来分析,可能不太容易搞清楚事务的前因后果,我想还是用老办法,从一个例子入手吧。
在WindowManagerService.java中有一个函数之前已分析过,现在再看看,代码如下所示:
[—>WindowManagerService.java:WinState]
Surface createSurfaceLocked(){
Surface.openTransaction();//开始一次transaction。
try{
try{
mSurfaceX=mFrame.left+mXOffset;
mSurfaceY=mFrame.top+mYOffset;
//设置Surface的位置。
mSurface.setPosition(mSurfaceX,mSurfaceY);
……
}
}finally{
Surface.closeTransaction();//关闭这次事务。
}
这个例子很好地展示了事务的调用流程,它会依次调用:
openTransaction
setPosition
closeTransaction
下面就来分析这几个函数的调用。
1.openTransaction分析
看JNI对应的函数,代码如下所示:
[—>android_View_Surface.cpp]
static void Surface_openTransaction(JNIEnv*env,jobject clazz)
{
//调用SurfaceComposerClient的openGlobalTransaction函数。
SurfaceComposerClient:openGlobalTransaction();
}
下面转到SurfaceComposerClient,代码如下所示:
[—>SurfaceComposerClient.cpp]
void SurfaceComposerClient:openGlobalTransaction()
{
Mutex:Autolock_l(gLock);
……
const size_t N=gActiveConnections.size();
for(size_t i=0;i<N;i++){
sp<SurfaceComposerClient>
client(gActiveConnections.valueAt(i).promote());
//gOpenTransactions存储当前提交事务请求的Client。
if(client!=0&&gOpenTransactions.indexOf(client)<0){
//Client是保存在全局变量gActiveConnections中的SurfaceComposerClient
//对象,调用它的openTransaction。
if(client->openTransaction()==NO_ERROR){
if(gOpenTransactions.add(client)<0){
client->closeTransaction();
}
}
……
}
}
}
上面是一个静态函数,内部调用了各个SurfaceComposerClient对象的openTranscation,代码如下所示:
[—>SurfaceComposerClient.cpp]
status_t SurfaceComposerClient:openTransaction()
{
if(mStatus!=NO_ERROR)
return mStatus;
Mutex:Autolock_l(mLock);
mTransactionOpen++;//一个计数值,用来控制事务的提交。
if(mPrebuiltLayerState==0){
mPrebuiltLayerState=new layer_state_t;
}
return NO_ERROR;
}
layer_state_t是用来保存Surface的一些信息的,比如位置、宽、高等信息。实际上,调用的setPosition等函数,就是为了改变这个layer_state_t中的值。
2.setPosition分析
上文说过,SFC中有一个layer_state_t对象用来保存Surface的各种信息。这里以setPosition为例来看它的使用情况。这个函数是用来改变Surface在屏幕上的位置的,代码如下所示:
[—>android_View_Surface.cpp]
static void Surface_setPosition(JNIEnv*env,jobject clazz,jint x,jint y)
{
const sp<SurfaceControl>&surface(getSurfaceControl(env,clazz));
if(surface==0)return;
status_t err=surface->setPosition(x,y);
}
[—>Surface.cpp]
status_t SurfaceControl:setPosition(int32_t x,int32_t y){
const sp<SurfaceComposerClient>&client(mClient);
status_t err=validate();
if(err<0)return err;
//调用SurfaceComposerClient的setPosition函数。
return client->setPosition(mToken,x,y);
}
[—>SurfaceComposerClient.cpp]
status_t SurfaceComposerClient:setPosition(SurfaceID id,int32_t x,int32_t y)
{
layer_state_t*s=_lockLayerState(id);//找到对应的layer_state_t。
if(!s)return BAD_INDEX;
s->what|=ISurfaceComposer:ePositionChanged;
s->x=x;
s->y=y;//上面几句修改了这块layer的参数。
_unlockLayerState();//该函数将unlock一个同步对象,其他没有做什么工作。
return NO_ERROR;
}
setPosition修改了layer_state_t中的一些参数,那么,这个状态是什么时候传递到SurfaceFlinger中的呢?
3.closeTransaction分析
相信读者此时已明白为什么叫“事务”了。原来,在openTransaction和closeTransaction中可以有很多操作,然后会由closeTransaction一次性地把这些修改提交到SF上,来看代码:
[—>android_View_Surface.cpp]
static void Surface_closeTransaction(JNIEnv*env,jobject clazz)
{
SurfaceComposerClient:closeGlobalTransaction();
}
[—>SurfaceComposerClient.cpp]
void SurfaceComposerClient:closeGlobalTransaction()
{
……
const size_t N=clients.size();
sp<ISurfaceComposer>sm(getComposerService());
//①先调用SF的openGlobalTransaction。
sm->openGlobalTransaction();
for(size_t i=0;i<N;i++){
//②然后调用每个SurfaceComposerClient对象的closeTransaction。
clients[i]->closeTransaction();
}
//③最后调用SF的closeGlobalTransaction。
sm->closeGlobalTransaction();
}
上面一共列出了三个函数,它们都是跨进程的调用,下面对其一一进行分析。
(1)SurfaceFlinger的openGlobalTransaction分析
这个函数其实很简单,略看一下就行了。
[—>SurfaceFlinger.cpp]
void SurfaceFlinger:openGlobalTransaction()
{
android_atomic_inc(&mTransactionCount);//又是一个计数控制。
}
(2)SurfaceComposerClient的closeTransaction分析
代码如下所示:
[—>SurfaceComposerClient.cpp]
status_t SurfaceComposerClient:closeTransaction()
{
if(mStatus!=NO_ERROR)
return mStatus;
Mutex:Autolock_l(mLock);
……
const ssize_t count=mStates.size();
if(count){
//mStates是这个SurfaceComposerClient中保存的所有layer_state_t数组,也就是
//每个Surface一个。然后调用跨进程的setState。
mClient->setState(count,mStates.array());
mStates.clear();
}
return NO_ERROR;
}
BClient的setState,最终会转到SF的setClientState上,代码如下所示:
[—>SurfaceFlinger.cpp]
status_t SurfaceFlinger:setClientState(ClientID cid,int32_t count,
const layer_state_t*states)
{
Mutex:Autolock_l(mStateLock);
uint32_t flags=0;
cid<<=16;
for(int i=0;i<count;i++){
const layer_state_t&s=states[i];
sp<LayerBaseClient>layer(getLayerUser_l(s.surface|cid));
if(layer!=0){
const uint32_t what=s.what;
if(what&ePositionChanged){
if(layer->setPosition(s.x,s.y))
//eTraversalNeeded表示需要遍历所有显示层。
flags|=eTraversalNeeded;
}
……
if(flags){
setTransactionFlags(flags);//这里将会触发threadLoop的事件。
}
return NO_ERROR;
}
[—>SurfaceFlinger.cpp]
uint32_t SurfaceFlinger:setTransactionFlags(uint32_t flags,nsecs_t delay)
{
uint32_t old=android_atomic_or(flags,&mTransactionFlags);
if((old&flags)==0){
if(delay>0){
signalDelayedEvent(delay);
}else{
signalEvent();//设置完mTransactionFlags后,触发事件。
}
}
return old;
}
(3)SurfaceFlinger的closeGlobalTransaction分析
来看代码:
[—>SurfaceFlinger.cpp]
void SurfaceFlinger:closeGlobalTransaction()
{
if(android_atomic_dec(&mTransactionCount)==1){
//注意下面语句的执行条件,当mTransactionCount变为零时才执行,这意味着
//openGlobalTransaction两次的话,只有最后一个closeGlobalTransaction调用
//才会真正地提交事务。
signalEvent();
Mutex:Autolock_l(mStateLock);
//如果这次事务涉及尺寸调整,则需要等一段时间。
while(mResizeTransationPending){
status_t err=mTransactionCV.waitRelative(mStateLock,s2ns(5));
if(CC_UNLIKELY(err!=NO_ERROR)){
mResizeTransationPending=false;
break;
}
}
}
}
关于事务的目的,相信读者已经比较清楚了:
就是将一些控制操作(例如setPosition)的修改结果一次性地传递给SF进行处理。
那么,哪些操作需要通过事务来传递呢?查看Surface.h可以知道,下面这些操作需要通过事务来传递(这里只列出了几个经常用的函数):setPosition、setAlpha、show/hide、setSize、setFlag等。
由于这些修改不像重绘那么简单,有时它会涉及其他的显示层,例如在显示层A的位置调整后,之前被A遮住的显示层B,现在可能变得可见了。对于这种情况,所提交的事务会设置eTraversalNeeded标志,这个标志表示要遍历所有显示层进行处理。关于这一点,我们可以看看工作线程中的事务处理。
4.工作线程中的事务处理
还是从代码入手分析,如下所示:
[—>SurfaceFlinger.cpp]
bool SurfaceFlinger:threadLoop()
{
waitForEvent();
if(LIKELY(mTransactionCount==0)){
const uint32_t mask=eTransactionNeeded|eTraversalNeeded;
uint32_t transactionFlags=getTransactionFlags(mask);
if(LIKELY(transactionFlags)){
handleTransaction(transactionFlags);
}
}
……
}
getTransactionFlags函数的实现蛮有意思,不妨看看其代码,如下所示:
[—>SurfaceFlinger.cpp]
uint32_t SurfaceFlinger:getTransactionFlags(uint32_t flags)
{
//先通过原子操作去掉mTransactionFlags中对应的位。
//而后原子操作返回的旧值和flags进行与操作
return android_atomic_and(~flags,&mTransactionFlags)&flags;
}
getTransactionFlags所做的工作不仅仅是get那么简单,它还设置了mTransactionFlags,从这个角度来看,getTransactionFlags这个名字有点名不副实。
接着来看最重要的handleTransaction函数,代码如下所示:
[—>SurfaceFlinger.cpp]
void SurfaceFlinger:handleTransaction(uint32_t transactionFlags)
{
Vector<sp<LayerBase>>ditchedLayers;
{
Mutex:Autolock_l(mStateLock);
//调用handleTransactionLocked函数处理。
handleTransactionLocked(transactionFlags,ditchedLayers);
}
const size_t count=ditchedLayers.size();
for(size_t i=0;i<count;i++){
if(ditchedLayers[i]!=0){
//ditch是丢弃的意思,有些显示层可能被hide了,所以这里做些收尾的工作。
ditchedLayers[i]->ditch();
}
}
}
[—>SurfaceFlinger.cpp]
void SurfaceFlinger:handleTransactionLocked(
uint32_t transactionFlags,Vector<sp<LayerBase>>&ditchedLayers)
{
//这里使用了mCurrentState,它的layersSortedByZ数组存储了SF中所有的显示层。
const LayerVector¤tLayers(mCurrentState.layersSortedByZ);
const size_t count=currentLayers.size();
const bool layersNeedTransaction=transactionFlags&eTraversalNeeded;
//如果需要遍历所有显示层的话。
if(layersNeedTransaction){
for(size_t i=0;i<count;i++){
const sp<LayerBase>&layer=currentLayers[i];
uint32_t trFlags=layer->getTransactionFlags(eTransactionNeeded);
if(!trFlags)continue;
//调用各个显示层的doTransaction函数。
const uint32_t flags=layer->doTransaction(0);
if(flags&Layer:eVisibleRegion)
mVisibleRegionsDirty=true;
}
}
if(transactionFlags&eTransactionNeeded){
if(mCurrentState.orientation!=mDrawingState.orientation){
//横竖屏如果发生切换,需要对应变换设置。
const int dpy=0;
const int orientation=mCurrentState.orientation;
const uint32_t type=mCurrentState.orientationType;
GraphicPlane&plane(graphicPlane(dpy));
plane.setOrientation(orientation);
……
}
/*
mLayersRemoved变量在显示层被移除的时候设置,例如removeLayer函数,这些函数也会触发handleTranscation函数的执行。
*/
if(mLayersRemoved){
mLayersRemoved=false;
mVisibleRegionsDirty=true;
const LayerVector&previousLayers(mDrawingState.layersSortedByZ);
const size_t count=previousLayers.size();
for(size_t i=0;i<count;i++){
const sp<LayerBase>&layer(previousLayers[i]);
if(currentLayers.indexOf(layer)<0){
ditchedLayers.add(layer);
mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
}
}
}
free_resources_l();
}
//提交事务处理,有必要进去看看。
commitTransaction();
}
每个显示层对事务的具体处理,都在它们的doTransaction函数中,读者若有兴趣,可进去看看。需要说明的是,每个显示层内部也有一个状态变量,doTransaction会更新这些状态变量。
回到上面的函数,最后它将调用commitTransaction提交事务,代码如下所示:
[—>SurfaceFlinger.cpp]
void SurfaceFlinger:commitTransaction()
{
//mDrawingState将使用更新后的mCurrentState。
mDrawingState=mCurrentState;
mResizeTransationPending=false;
//触发一个条件变量,这样等待在closeGlobalTransaction函数中的线程可以放心地返回了。
mTransactionCV.broadcast();
}