天天看點

Android GUI系統之SurfaceFlinger(07)服務端分析2-handleMessageTransaction處理

該系列文章總綱連結:Android GUI系統之SurfaceFlinger 系列文章目錄

本章關鍵點總結 & 說明:

Android GUI系統之SurfaceFlinger(07)服務端分析2-handleMessageTransaction處理

本章節思維導圖如上。主要講述了SurfaceFlinger 處理Vsync機制的流程。主要分析handleMessageTransaction 處理方法。

繼續上一節(Android GUI系統之SurfaceFlinger(06)服務端分析1-處理VSYNC)的分析,這裡的INVALIDATE對應mQueue.mFlinger->onMessageReceived(message.what)方法的執行,onMessageReceived代碼實作如下:

void SurfaceFlinger::onMessageReceived(int32_t what) {
    switch (what) {
        case MessageQueue::TRANSACTION: {
            handleMessageTransaction();
            break;
        }
        case MessageQueue::INVALIDATE: {
            //關鍵語句
            bool refreshNeeded = handleMessageTransaction();//1 
            refreshNeeded |= handleMessageInvalidate();//2 
            refreshNeeded |= mRepaintEverything;
            if (refreshNeeded) {
                signalRefresh();//3
            }
            break;
        }
        case MessageQueue::REFRESH: {
            handleMessageRefresh();
            break;
        }
    }
}
           

針對INVALIDATE消息,關鍵執行代碼中辨別的幾句話。我們對其分别技能型詳細的分析

handleMessageTransaction

handleMessageTransaction的代碼實作如下:

bool SurfaceFlinger::handleMessageTransaction() {
    uint32_t transactionFlags = peekTransactionFlags(eTransactionMask);
    if (transactionFlags) {
        handleTransaction(transactionFlags);
        return true;
    }
    return false;
}
           

繼續分析這裡的handleTransaction,代碼如下:

void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
    State drawingState(mDrawingState);
    Mutex::Autolock _l(mStateLock);
    const nsecs_t now = systemTime();
    mDebugInTransaction = now;
    //産生一個新的transactionFlags變量  
    transactionFlags = getTransactionFlags(eTransactionMask);
    handleTransactionLocked(transactionFlags);

    mLastTransactionTime = systemTime() - now;
    mDebugInTransaction = 0;
    invalidateHwcGeometry();
}
           

繼續分析handleTransactionLocked,這也是本部分分析的重點,因為handleTransactionLocked的代碼比較長,這類分成5個部分進行解讀。

1 處理Layer的事務

抽取第一部分代碼,實作如下:

void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
    const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
    const size_t count = currentLayers.size();

    if (transactionFlags & eTraversalNeeded) {
        for (size_t i=0 ; i<count ; i++) {
            const sp<Layer>& layer(currentLayers[i]);
            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
            if (!trFlags) continue;

            const uint32_t flags = layer->doTransaction(0);
            if (flags & Layer::eVisibleRegion)
                mVisibleRegionsDirty = true;
        }
    }
    //...
}
           

這裡周遊每一個Layer,根據eTraversalNeeded标志來決定是否要檢查Layer對象。如果Layer中有eTransactionNeeded标志,則傳回非0值,然後調用它的doTransaction函數。Layer的doTransaction函數傳回的flags如果有eVisibleRegion,則說明該Layer需要更新,mVisibleRegionsDirty設定為true。這裡繼續分析Layer的doTransaction函數,代碼如下:

uint32_t Layer::doTransaction(uint32_t flags) {
    const Layer::State& s(getDrawingState());//上次繪制使用的State對象  
    const Layer::State& c(getCurrentState());//目前繪制使用的State對象  

    const bool sizeChanged = (c.requested.w != s.requested.w) ||
                             (c.requested.h != s.requested.h);
    //如果兩個對象的大小不相等,說明Layer的尺寸發生變化  
    if (sizeChanged) {
        mSurfaceFlingerConsumer->setDefaultBufferSize(
                c.requested.w, c.requested.h);
    }

    if (!isFixedSize()) {
        const bool resizePending = (c.requested.w != c.active.w) ||
                                   (c.requested.h != c.active.h);
        //如果兩者不一樣,flags加上不更新Geometry标志
        if (resizePending) {
            flags |= eDontUpdateGeometryState;
        }
    }

    if (flags & eDontUpdateGeometryState)  {
    } else {
        //如果沒有eDontUpdateGeometryState标志,更新active的值為request
        Layer::State& editCurrentState(getCurrentState());
        editCurrentState.active = c.requested;
    }

    if (s.active != c.active) {
        // 如果目前state的active和以前的State的active不等,設定更新标志  
        flags |= Layer::eVisibleRegion;
    }

    if (c.sequence != s.sequence) {
        //如果目前state的sequence和以前state的sequence不等,設定更新标志 
        flags |= eVisibleRegion;
        this->contentDirty = true;

        // we may use linear filtering, if the matrix scales us
        const uint8_t type = c.transform.getType();
        mNeedsFiltering = (!c.transform.preserveRects() ||
                (type >= Transform::SCALE));
    }

    //将mCurrentState的值賦給mDrawingState
    commitTransaction();
    return flags;
}
           

這裡留意:Layer類中的兩個類型為Layer::State的成員變量mDrawingState、mCurrentState,Layer::State類型代碼如下:

struct State {  
    Geometry active;	//實際大小  
    Geometry requested;	//使用者大小  
    uint32_t z;			//Z軸值  
    uint32_t layerStack;//和顯示裝置的關聯值  
    uint8_t alpha;
    uint8_t flags; 
    uint8_t reserved[2];  
    int32_t sequence; 	//序列值,Layer的屬性變化一次,這個值就加1  
    Transform transform;
    Region activeTransparentRegion;//實際的透明區域  
    Region requestedTransparentRegion;//使用者層的透明區域  
};
           

Layer對象在繪制圖形時,使用的是mDrawingState變量,使用者調用接口設定Layer對象屬性是,設定的值儲存在mCurrentState對象中,這樣就不會因為使用者的操作而幹擾Layer對象的繪制了。是以這裡有兩個對象。

接下來對State 結構體中的一些變量進行說明:

  1. Geometry字段:State的結構中有兩個Geometry字段,active和requested。他們表示layer的尺寸,其中requested儲存是使用者設定的尺寸,而active儲存的值通過計算後的實際尺寸。
  2. layerStack字段:它是使用者指定的一個值,使用者可以給DisplayDevice也指定一個layerStack值,隻有Layer對象和DisplayDevice對象的layerStack相等,這個Layer才能在這個顯示裝置上輸出,這樣的好處是可以讓顯示裝置隻顯示某個Surface的内容。例如,可以讓HDMI顯示裝置隻顯示手機上播放視訊的Surface視窗,但不顯示Activity視窗。
  3. sequence字段:它是一個序列值,每當使用者調用了Layer的接口,例如setAlpha、setSize或者setLayer等改變Layer對象屬性的哈數,這個值都會加1。是以在doTransaction函數中能通過比較sequence值來判斷Layer的屬性值有沒有變化。

可以看到Layer::State中的layerStack中會對比DisplayDeviceState對象的layerStack,是以分析下DisplayDeviceState,代碼如下:

struct DisplayDeviceState {
        DisplayDeviceState();
        DisplayDeviceState(DisplayDevice::DisplayType type);
        bool isValid() const { return type >= 0; }
        bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
        bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
        DisplayDevice::DisplayType type;
        sp<IGraphicBufferProducer> surface;
        uint32_t layerStack;//關鍵點
        Rect viewport;
        Rect frame;
        uint8_t orientation;
        uint32_t width, height;
        String8 displayName;
        bool isSecure;
    };
           

可以說這裡的layerStack和Layer的State中的layerStack如果相等,則Layer可以在該State對應的DisplayDevice中顯示。

2 處理顯示裝置的變化

抽取第二部分代碼,實作如下:

//...
    if (transactionFlags & eDisplayTransactionNeeded) {
        //得到目前顯示裝置清單和之前使用的顯示裝置清單
        const KeyedVector<  wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);
        const KeyedVector<  wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
        if (!curr.isIdenticalTo(draw)) {
            mVisibleRegionsDirty = true;
            const size_t cc = curr.size();//現在顯示裝置的數量  
                  size_t dc = draw.size();//以前顯示裝置的數量

            for (size_t i=0 ; i<dc ; i++) {
                const ssize_t j = curr.indexOfKey(draw.keyAt(i));
                if (j < 0) {//裝置被删除
                    // in drawing state but not in current state
                    if (!draw[i].isMainDisplay()) {
                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
                        defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
                        sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
                        if (hw != NULL)
                            hw->disconnect(getHwComposer());
                        if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
                            mEventThread->onHotplugReceived(draw[i].type, false);
                        //如果不是主裝置移除它
                        mDisplays.removeItem(draw.keyAt(i));
                    } else {
                        ALOGW("trying to remove the main display");
                    }
                } else {裝置還在,再檢查有沒有其他變化
                    // this display is in both lists. see if something changed.
                    const DisplayDeviceState& state(curr[j]);
                    const wp<IBinder>& display(curr.keyAt(j));
                    if (state.surface->asBinder() != draw[i].surface->asBinder()) {
                        sp<DisplayDevice> hw(getDisplayDevice(display));
                        if (hw != NULL)
                            hw->disconnect(getHwComposer());
                        mDisplays.removeItem(display);
                        mDrawingState.displays.removeItemsAt(i);
                        dc--; i--;
                        // at this point we must loop to the next item
                        continue;
                    }

                    const sp<DisplayDevice> disp(getDisplayDevice(display));
                    if (disp != NULL) {
                        //兩個對象layerStack不等,使用目前對象的  
                        if (state.layerStack != draw[i].layerStack) {
                            disp->setLayerStack(state.layerStack);
                        }
                        if ((state.orientation != draw[i].orientation)
                                || (state.viewport != draw[i].viewport)
                                || (state.frame != draw[i].frame))
                        {
                            disp->setProjection(state.orientation,
                                    state.viewport, state.frame);
                        }
                        if (state.width != draw[i].width || state.height != draw[i].height) {
                            disp->setDisplaySize(state.width, state.height);
                        }
                    }
                }
            }
            //處理顯示裝置增加的情況。。。
        }
    }
    //...
           

這段代碼主要是處理顯示裝置的變化:

  1. 移除不需要的顯示裝置,将其對應的DisplayDevice移除
  2. 對于發生變化的顯示裝置(設定Surface、重置layerStack、旋轉。。。),就需要重置顯示對象的屬性
  3. 對于新增加的顯示裝置,建立DisplayDevice并加入到系統

3 設定TransfromHit

抽取第三部分代碼,實作如下:

//...
    if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
        sp<const DisplayDevice> disp;
        uint32_t currentlayerStack = 0;
        for (size_t i=0; i<count; i++) {
            const sp<Layer>& layer(currentLayers[i]);
            uint32_t layerStack = layer->getDrawingState().layerStack;
            if (i==0 || currentlayerStack != layerStack) {
                currentlayerStack = layerStack;
                disp.clear();
                for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
                    sp<const DisplayDevice> hw(mDisplays[dpy]);
                    if (hw->getLayerStack() == currentlayerStack) {
                        if (disp == NULL) {
                            disp = hw;
                        } else {
                            disp = NULL;
                            break;
                        }
                    }
                }
            }
            if (disp == NULL) {
                disp = getDefaultDisplayDevice();
            }
            //設定Layer對象的TransformHint
            layer->updateTransformHint(disp);
        }
    }
    //...
           

這段代碼根據每種顯示裝置的不同,設定和顯示裝置關聯在一起的Layer(主要看Layer的layerStack是否和DisplayDevice的layerStack一緻)的TransformHint(主要指裝置的顯示方向orientation)

4 處理Layer增減情況

抽取第四部分代碼,實作如下:

//...
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    if (currentLayers.size() > layers.size()) {
        //如果有Layer加入,設定需要更新 
        mVisibleRegionsDirty = true;
    }

    if (mLayersRemoved) {//有Layer删除
        mLayersRemoved = false;
        mVisibleRegionsDirty = true;
        const size_t count = layers.size();
        for (size_t i=0 ; i<count ; i++) {
            const sp<Layer>& layer(layers[i]);
            //如果這個Layer不存在,則把它的所在區域設定為需要更新的區域
            if (currentLayers.indexOf(layer) < 0) {
                const Layer::State& s(layer->getDrawingState());
                Region visibleReg = s.transform.transform(
                        Region(Rect(s.active.w, s.active.h)));
                invalidateLayerStack(s.layerStack, visibleReg);
            }
        }
    }
    //...
           

這段代碼處理Layer的增減情況:

  1. 如果有Layer增加,需要重新計算裝置的更新區域,mVisibleRegionsDirty設定為true
  2. 如果有Layer被删除,需要把Layer的可見區域加入到系統需要更新的區域中

5 設定mDrawingState

抽取第五部分代碼,實作如下:

//...
    commitTransaction();
    updateCursorAsync();
}
           

分别對commitTransaction和updateCursorAsync進行簡單的分析。

5.1 commitTransaction

代碼實作如下:

void SurfaceFlinger::commitTransaction()
{
    if (!mLayersPendingRemoval.isEmpty()) {
        // Notify removed layers now that they can't be drawn from
        for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
            mLayersPendingRemoval[i]->onRemoved();
        }
        mLayersPendingRemoval.clear();
    }

    mAnimCompositionPending = mAnimTransactionPending;

    mDrawingState = mCurrentState;//關鍵點
    mTransactionPending = false;
    mAnimTransactionPending = false;
    mTransactionCV.broadcast();
}
           

commitTransaction函數最關鍵的作用是把mDrawingState的值設定成mCurrentState的值。

5.2 updateCursorAsync

代碼實作如下:

void SurfaceFlinger::updateCursorAsync()
{
    HWComposer& hwc(getHwComposer());
    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
        sp<const DisplayDevice> hw(mDisplays[dpy]);
        const int32_t id = hw->getHwcDisplayId();
        if (id < 0) {
            continue;
        }
        const Vector< sp<Layer> >& currentLayers(
            hw->getVisibleLayersSortedByZ());
        const size_t count = currentLayers.size();
        HWComposer::LayerListIterator cur = hwc.begin(id);
        const HWComposer::LayerListIterator end = hwc.end(id);
        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
            if (cur->getCompositionType() != HWC_CURSOR_OVERLAY) {
                continue;
            }
            const sp<Layer>& layer(currentLayers[i]);
            Rect cursorPos = layer->getPosition(hw);
            hwc.setCursorPositionAsync(id, cursorPos);
            break;
        }
    }
}
           

updateCursorAsync函數會更新所有顯示裝置中光标的位置。

6 總結

該部分代碼主要是處理事物:

  1. 周遊每一個Layer,根據條件執行對應的doTransaction,根據傳回值設定mVisibleRegionsDirty
  2. 處理顯示裝置的變化:增加/删除/變化
  3. 對Layer的TransfromHit(旋轉角度)進行設定
  4. 處理SurfaceFlinger本身的事物:Layer的增減情況

總結下,雖然處理了很多事物,但主要是設定一些flag,但并未對相關的Buffer進行實際的操作。handleTransaction函數的作用的就是處理系統在兩次重新整理期間的各種變化。SurfaceFlinger子產品 中不管是SurfaceFlinger類還是Layer類,都采用了雙緩沖的方式來儲存他們的屬性,這樣的好處是剛改變SurfaceFlinger對象或者Layer類對象的屬性時不需要上鎖,這很大程度上提高了系統效率。隻有在最後的圖像輸出才會進行一次上鎖,并将記憶體的屬性變化進行處理。正是以,應用程序必須收到VSync信号才開始改變Surface中Buffer的内容。