8.5.3 Transaction分析

最后更新于:2022-04-02 05:52:50

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** ~~~ voidSurfaceComposerClient::openGlobalTransaction() { Mutex::Autolock _l(gLock); ...... constsize_t N = gActiveConnections.size(); for(size_t i=0; iclient(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_tSurfaceComposerClient::openTransaction() { if(mStatus != NO_ERROR) return mStatus; Mutex::Autolock _l(mLock); mTransactionOpen++; //一个计数值,用来控制事务的提交。 if(mPrebuiltLayerState == 0) { mPrebuiltLayerState = new layer_state_t; } returnNO_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) { constsp& 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) { constsp& client(mClient); status_t err = validate(); if (err < 0) return err; //调用SurfaceComposerClient的setPosition函数 returnclient->setPosition(mToken, x, y); } ~~~ **SurfaceComposerClient.cpp** ~~~ status_tSurfaceComposerClient::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一个同步对象,其他没有做什么工作 returnNO_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** ~~~ voidSurfaceComposerClient::closeGlobalTransaction() { ...... const size_t N = clients.size(); spsm(getComposerService()); //①先调用SF的openGlobalTransaction sm->openGlobalTransaction(); for (size_t i=0; icloseTransaction(); } //③最后调用SF的closeGlobalTransaction sm->closeGlobalTransaction(); } ~~~ 上面一共列出了三个函数,它们都是跨进程的调用,下面对其一一进行分析。 (1)SurfaceFlinger的openGlobalTransaction分析 这个函数其实很简单,略看就行了。 **SurfaceFlinger.cpp** ~~~ void SurfaceFlinger::openGlobalTransaction() { android_atomic_inc(&mTransactionCount);//又是一个计数控制 } ~~~ (2)SurfaceComposerClient的closeTransaction分析 代码如下所示: **SurfaceComposerClient.cpp** ~~~ status_tSurfaceComposerClient::closeTransaction() { if(mStatus != NO_ERROR) return mStatus; Mutex::Autolock _l(mLock); ...... constssize_t count = mStates.size(); if (count) { //mStates是这个SurfaceComposerClient中保存的所有layer_state_t数组,也就是 //每个Surface一个。然后调用跨进程的setState mClient->setState(count, mStates.array()); mStates.clear(); } returnNO_ERROR; } ~~~ BClient的setState,最终会转到SF的setClientState上,代码如下所示: **SurfaceFlinger.cpp** ~~~ status_t SurfaceFlinger::setClientState(ClientIDcid, int32_t count, const layer_state_t*states) { Mutex::Autolock _l(mStateLock); uint32_t flags = 0; cid<<= 16; for(int i=0 ; i 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的事件。 } returnNO_ERROR; } ~~~ **SurfaceFlinger.cpp** ~~~ uint32_tSurfaceFlinger::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后,触发事件。 } } returnold; } ~~~ (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_ttransactionFlags = getTransactionFlags(mask); if(LIKELY(transactionFlags)) { handleTransaction(transactionFlags); } } ... } ~~~ getTransactionFlags函数的实现蛮有意思,不妨看看其代码,如下所示: **SurfaceFlinger.cpp** ~~~ uint32_t SurfaceFlinger::getTransactionFlags(uint32_tflags) { //先通过原子操作去掉mTransactionFlags中对应的位。 //而后原子操作返回的旧值和flags进行与操作 return android_atomic_and(~flags,&mTransactionFlags) & flags; } ~~~ getTransactionFlags所做的工作不仅仅是get那么简单,它还设置了mTransactionFlags,从这个角度来看,getTransactionFlags这个名字有点名不副实。 接着来看最重要的handleTransaction函数,代码如下所示: **SurfaceFlinger.cpp** ~~~ void SurfaceFlinger::handleTransaction(uint32_ttransactionFlags) { Vector< sp > ditchedLayers; { Mutex::Autolock _l(mStateLock); //调用handleTransactionLocked函数处理 handleTransactionLocked(transactionFlags, ditchedLayers); } constsize_t count = ditchedLayers.size(); for(size_t i=0 ; iditch(); } } } ~~~ **SurfaceFlinger.cpp** ~~~ void SurfaceFlinger::handleTransactionLocked( uint32_t transactionFlags, Vector< sp >&ditchedLayers) { //这里使用了mCurrentState,它的layersSortedByZ数组存储了SF中所有的显示层 constLayerVector& currentLayers(mCurrentState.layersSortedByZ); constsize_t count = currentLayers.size(); constbool layersNeedTransaction = transactionFlags & eTraversalNeeded; //如果需要遍历所有显示的话。 if(layersNeedTransaction) { for (size_t i=0 ; i& layer = currentLayers[i]; uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded); if (!trFlags) continue; //调用各个显示层的doTransaction函数。 constuint32_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& layer(previousLayers[i]); if (currentLayers.indexOf( layer ) < 0) { ditchedLayers.add(layer); mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen); } } } free_resources_l(); } //提交事务处理,有必要进去看看。 commitTransaction(); } ~~~ 每个显示层对事务的具体处理,都在它们的doTranscation函数中,读者若有兴趣,可进去看看。需要说明的是,每个显示层内部也有一个状态变量,doTransaction会更新这些状态变量。 回到上面的函数,最后它将调用commitTransaction提交事务,代码如下所示: **SurfaceFlinger.cpp** ~~~ void SurfaceFlinger::commitTransaction() { //mDrawingState将使用更新后的mCurrentState mDrawingState = mCurrentState; mResizeTransationPending = false; //触发一个条件变量,这样等待在closeGlobalTransaction函数中的线程可以放心地返回了。 mTransactionCV.broadcast(); } ~~~
';