「Android」SurfaceFlinger分析

本篇針對surfaceFlinger模塊進行分析,目錄以下:html

一、SurfaceFlinger功能android

  1.一、BufferQueue原理(native/libs/gui模塊)windows

  1.2   layer顯示內存分配(native/libs/ui模塊)app

  1.三、surfaceFlinger處理(native/.../surfaceFlinger模塊composer

二、工程代碼解析:socket

  2.一、surfaceFlinger啓動過程函數

  2.二、surfaceFlinger事務處理 oop

三、總結(處理流程、交互模塊)post

***********************************************************×*********************************×*******動畫

 

一、SurfaceFlinger功能:

surfaceflinger做用是接受多個來源的圖形顯示數據,將他們合成,而後發送到顯示設備。
好比打開應用,常見的有三層顯示,頂部的statusbar底部或者側面的導航欄以及應用的界面,每一個層是單獨更新和渲染,這些界面都是有surfaceflinger合成一個刷新到硬件顯示。
在顯示過程當中使用到了 bufferqueue,surfaceflinger做爲consumer方,好比windowmanager管理的surface做爲生產方產生頁面,交由surfaceflinger進行合成。

1.一、BufferQueue原理(和SF交互)

bufferqueue分爲生產者和消費者
好比應用經過windowsmanager分配一個surface,須要分配(dequeueBuffer)顯示空間在上面進行繪圖,在圖形繪製完成後須要推送(queueBuffer)到surfaceflinger進行合成顯示。
surfaceflinger做爲消費者,經過acquireBuffer()獲得一個要合成的圖形,在合成完畢後再releaseBuffer()將圖形釋放。
(1)在bufferQueuei所在目錄下  ComposerService 爲單例模式負責與surfaceflinger 創建binder鏈接,在native/libs/gui庫
代碼以下:
class ComposerService : public Singleton<ComposerService>
{
    sp<ISurfaceComposer> mComposerService;
    sp<IBinder::DeathRecipient> mDeathObserver;
    Mutex mLock;

    ComposerService();
    void connectLocked();
    void composerServiceDied();
    friend class Singleton<ComposerService>;
public:

    // Get a connection to the Composer Service.  This will block until
    // a connection is established.即getComposerService
    static sp<ISurfaceComposer> getComposerService();
};

(2)ComposerService 爲單例模式負責與surfaceflinger創建binder鏈接;

(3)SurfaceComposerClient則在於surfaceflinger創建鏈接後(即getComposerService)創建與Client的鏈接,

  經過client調用createSurface,而後返回SurfaceControl;

(4)SurfaceControl負責這個顯示層的控制。

sp<Surface> SurfaceControl::getSurface() const
{
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == 0) {
        // This surface is always consumed by SurfaceFlinger, so the
        // producerControlledByApp value doesn't matter; using false.
        mSurfaceData = new Surface(mGraphicBufferProducer, false);
    }
    return mSurfaceData;
}
經過SurfaceControl::getSurface(),獲得的真正的顯示層,這樣以後能夠經過Lock和unlock將surface空間分配繪圖,再返回給surfaceflinger。

1.2 layer顯示內存分配

(1)surface建立後獲得 mGraphicBufferProducer,new GraphicBuffer分配一個GraphicBuffer:

int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {.....}

(2) 在graphicbuffer.cpp中分配一個共享內存,在native/libs/ui模塊:

GraphicBuffer::GraphicBuffer(...){...}
status_t GraphicBuffer::initWithSize(...){...}

(3)GraphicBufferAllocator::get() 使用gralloc進行內存分配,分配完成後,獲得bufferIdx 將他發給client端也就是surface端

(4)返回虛擬地址給上層

 

1.三、surfaceFlinger處理

 上面建立一個surface後,surfaceflinger對應的是一個layer,當上層layer調用刷新後,onFrameAvailable被調用,通知surfaceflinger有layer更新

void BufferLayer::onFrameAvailable(const BufferItem& item) {
    mFlinger->signalLayerUpdate();
}

 

 

二、工程代碼解析:

2.一、surfaceFlinger啓動過程:

(代碼取自其餘博客提供下載的源碼https://blog.csdn.net/ztguang/article/details/64905058,Android7.0以上)

 一、surfaceFlinger代碼倉位置:/frameworks/native/services/surfaceflingers

    surfaceFlinger啓動進程的腳本是surfceFlinger.rc文件,內容以下:

1 service surfaceflinger /system/bin/surfaceflinger
2     class core
3     user system
4     group graphics drmrpc readproc
5     onrestart restart zygote
6     writepid /dev/stune/foreground/tasks

socket pdx/system/vr/display/client
stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
socket pdx/system/vr/display/manager
stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
socket pdx/system/vr/display/vsync
stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0

  注:在.bp腳本中會初始化該腳本,以後執行main_surfaceflinger.cpp文件 (rc文件有3個socket,用於跨進程通訊)

二、建立進程後執行main函數,main函數在frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp,main函數主要代碼以下:

int main(int, char**) {
   //忽略了SIGPIPE信號,由於在SurfaceFlinger的Client-Server模型中,或者說IPC機制中,極可能會觸發SIGPIPE信號,而這個信號的默認動做是終止進程
  ////當客戶端/服務端的socket關閉時,防止進程退出 signal(SIGPIPE, SIG_IGN);
// When SF is launched in its own process, limit the number of // binder threads to 4.即SF進程開啓後,線程池限制最大數量爲4 ProcessState::self()->setThreadPoolMaxThreadCount(4); // start the thread pool即啓動線程池
  //
大多數程序都是須要IPC的,這裏也須要,可是使用Binder機制是很繁瑣的,因此Android爲程序進程使用Binder機制封裝了兩個實現類:ProcessState、IPCThreadState
  //其中ProcessState負責打開Binder驅動,進行mmap等準備工做;IPCThreadState負責具體線程跟Binder驅動進行命令交互。
    sp<processstate> ps(ProcessState::self());
    ps->startThreadPool();
 
    // instantiate surfaceflinger即實例化,以及設置進程優先級、事物處理策略
    sp<surfaceflinger> flinger = new SurfaceFlinger();
 
    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
 
    set_sched_policy(0, SP_FOREGROUND);
 
#ifdef ENABLE_CPUSETS
    // Put most SurfaceFlinger threads in the system-background cpuset
    // Keeps us from unnecessarily using big cores
    // Do this after the binder thread pool init
    set_cpuset_policy(0, SP_SYSTEM);
#endif
 
    // initialize before clients can connect即初始化
    flinger->init();
 
    // publish surface flinger即發佈SF,註冊到ServiceManager,sp是strongponiter強指針(sp對象的析構函數調用RefBase的decStrong來減小強弱引用指針計數)
    sp<iservicemanager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
 
    // publish GpuService即註冊GPUservice
    sp<gpuservice> gpuservice = new GpuService();
    sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
 
    struct sched_param param = {0};
    param.sched_priority = 2;
    if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
        ALOGE("Couldn't set SCHED_FIFO");
    }
 
    // run surface flinger in this thread即運行當前線程
    flinger->run();
 
    return 0;
}

在執行main函數的時候,執行通過了如下過程: 

(1)建立SurfaceFlinger對象,在其構造函數中,主要是一些成員變量的初始化工做。在SurfaceFlinger.cpp中的構造函數代碼以下:

SurfaceFlinger::SurfaceFlinger()
    :   BnSurfaceComposer(),
        mTransactionFlags(0),
        mTransactionPending(false),
        mAnimTransactionPending(false),
        mLayersRemoved(false),
        mRepaintEverything(0),
        mRenderEngine(NULL),
        mBootTime(systemTime()),
        mBuiltinDisplays(),
        mVisibleRegionsDirty(false),
        mGeometryInvalid(false),
        mAnimCompositionPending(false),
        mDebugRegion(0),
        mDebugDDMS(0),
        mDebugDisableHWC(0),
        mDebugDisableTransformHint(0),
        mDebugInSwapBuffers(0),
        mLastSwapBufferTime(0),
        mDebugInTransaction(0),
        mLastTransactionTime(0),
        mBootFinished(false),
        mForceFullDamage(false),
        mPrimaryDispSync("PrimaryDispSync"),
        mPrimaryHWVsyncEnabled(false),
        mHWVsyncAvailable(false),
        mHasColorMatrix(false),
        mHasPoweredOff(false),
        mFrameBuckets(),
        mTotalTime(0),
        mLastSwapTime(0)
{......}

 

(2) 由於這裏的SurfaceFlinger對象是一個StrongPointer(強指針,見老羅博客https://blog.csdn.net/luoshengyang/article/details/6786239),因此首先會走到RefBaseonFirstRef方法。

void SurfaceFlinger::onFirstRef()
{
    mEventQueue.init(this);
}

       查看surfaceFlinger.h,發現mEventQueue是MessqgeQueue建立的對象。因此初始化會建立消息隊列須要的Handler、Looper。在相同目錄下的MessageQueue.cpp文件中:

void MessageQueue::init(const sp<surfaceflinger>& flinger)
{
    mFlinger = flinger;
    mLooper = new Looper(true);
    mHandler = new Handler(*this);
}

  此處MessageQueue不是常見的消息隊列,在surfaceFlinger目錄單獨編寫,mEventQueue更像是消息循環機制的管理者,其中包含了一個looper,一個handler。

  looper中的mMessageEnvelopes這個容器纔是真正存儲消息的地方:

/* MessageQueue.cpp */

void MessageQueue::waitMessage() {

         int32_tret = mLooper->pollOnce(-1);

}

 

  handler也不是常見的那個handler,而是Messagequeue中自定義的一個事件處理器,是專門爲surfaceflinger設計的,handler收到消息,進一步回調surfaceflinger中的onMessageReceived。

void MessageQueue::Handler::handleMessage(constMessage& message) {

         switch(message.what) {

                   caseINVALIDATE:

                            mQueue.mFlinger->onMessageReceived(message.what);

}        } 

(3)以後執行surfaceFlinger::init,方法主要實現的功能

  • 初始化EGL
  • 建立HWComposer
  • 初始化非虛擬顯示屏
  • 啓動EventThreada線程
  • 啓動開機動畫

在SurfaceFlinger.cpp中的代碼以下:

void SurfaceFlinger::init() {
    ALOGI(  "SurfaceFlinger's main thread ready to run. "
            "Initializing graphics H/W...");  //開始SF線程的準備工做,初始化graphics H/W

    { // Autolock scope
        Mutex::Autolock _l(mStateLock);

        // initialize EGL for the default display即初始化EGL,做爲默認顯示(EGL見https://blog.csdn.net/ieearth/article/details/71180457)
        mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        eglInitialize(mEGLDisplay, NULL, NULL);

        // start the EventThread開啓事件線程
        sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                vsyncPhaseOffsetNs, true, "app");
        mEventThread = new EventThread(vsyncSrc, *this);
        sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                sfVsyncPhaseOffsetNs, true, "sf");
        mSFEventThread = new EventThread(sfVsyncSrc, *this);
        mEventQueue.setEventThread(mSFEventThread);

        // set SFEventThread to SCHED_FIFO to minimize jitter
        struct sched_param param = {0};
        param.sched_priority = 2;
        if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
            ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
        }

        // Get a RenderEngine for the given display / config (can't fail)
        mRenderEngine = RenderEngine::create(mEGLDisplay,
                HAL_PIXEL_FORMAT_RGBA_8888);
    }

    // Drop the state lock while we initialize the hardware composer. We drop
    // the lock because on creation, it will call back into SurfaceFlinger to
    // initialize the primary display.即初始化硬件composer對象,和顯示設備交互,硬件顯示設備
    mHwc = new HWComposer(this);
    mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));

    Mutex::Autolock _l(mStateLock);

    // retrieve the EGL context that was selected/created即檢索建立的EGL上下文
    mEGLContext = mRenderEngine->getEGLContext();

    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
            "couldn't create EGLContext");

    // make the GLContext current so that we can create textures when creating
    // Layers (which may happens before we render something)即顯示設備
    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);

    mEventControlThread = new EventControlThread(this);
    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);//建立EventControl // initialize our drawing state
    mDrawingState = mCurrentState;

    // set initial conditions (e.g. unblank default device)即初始化顯示裝備
    initializeDisplays();

    mRenderEngine->primeCache();

    // start boot animation即啓動開機動畫
    startBootAnim();

    ALOGV("Done initializing");
}

(4)Android系統中有一個ServiceManager,專門用來管理全部的服務,而SurfaceFlinger不是由ServiceManager啓動的,所以須要向ServiceManager註冊SurfaceFlinger,同時還註冊了GpuService。(在main函數裏面註冊)

(5)執行SF的run方法,SurfaceFlinger::run,進入消息循環,SurfaceFlinger啓動成功,開始工做。代碼以下:

void SurfaceFlinger::run() {
    do {
        waitForEvent();
    } while (true);
}

(分析參考博客https://blog.csdn.net/u012439416/article/details/79733178)

waitForEvent方法以下:

mEventQueue.waitMessage();

MessageQueue的waitMessage方法也是一個do – while循環,裏面邏輯以下:

>阻塞消息

IPCThreadState::self()->flushCommands();
int32_t ret = mLooper->pollOnce(-1);

flushCommands方法主要是對binder驅動進行交互, 清理binder

pollOnce是消息機制,主要調用了epoll_wait函數,會阻塞,阻塞完了會分發消息隊列中的消息。這裏的消息只有本身在Handler中發的消息,還有在setEventThread中本身添加的消息。
>處理不一樣消息

 

2.二、工做流程

  在執行SF的run方法時,SurfaceFlinger::run,進入MessageQueue.cpp中的waitForEvent方法:

 

當Surface繪製完成後會發出一個Invalidate的消息給Surfaceflinger的等待線程,當waitForEvent接收到消息後就會交給onMessageReceivered去處理,處理過程當中會依次調用handleMessageTransaction、handleMessageInvalidate、handleMessageRefresh接口。
 (1)調用handleMessageTransaction時,會調用:

    > 有事務處理請求時,調用handleTransaction進行處理(getTransactionFlags)  

      > 調用handleTransactionLocked

      > commitTransactionao提交事務

    該函數主要處理以前對屏幕和應用程序窗口的改動。窗口狀態的改變只能在一個Transaction中進行。由於窗口狀態的改變可能形成本窗口和其餘窗口的可見區域變化,因此就必須從新來計算窗口的可見區域。在這個處理子過程當中Android會根據標誌位來對全部layer進行遍歷,一旦發現哪一個窗口的狀態發生了變化就設置標誌位以在未來從新計算這個窗口的可見區域。

 (2)調用handleMessageInvalidate時,會調用handlePageFlip

    > handlePageFlip繪製(Layer從FrontBuffer中取得新數據,並生成一張OpenGL中的紋理。如今Layer準備好了數據,下一步開始進行繪製)

    該函數主要調用handlePageFlip()函數,該函數主要是從各Layer對應的BufferQueue中拿圖形緩衝區數據,並根據內容更新髒區域。

   (3)handleMessageRefresh——進行合併和渲染輸出:

   (4)合併渲染完成後,該線程繼續等待下一個invalidate消息。

 

 

 

四、總結(處理流程、交互模塊)

4.一、處理流程

  首先SF的啓動過程:> 啓動進程腳本.rc

            > main_sf.cpp的main()函數

             >> 啓動線程池,設置線程最大數量

             >> 實例化(建立對象)SF.cpp

               >>> SF:SF構造函數,初始化一些成員變量

               >>> (強指針<p>)SF::onFirstRef執行到MessageQueue.cpp,執行init()建立Handler、Looper

             >> 設置進程優先級 

             >> 執行sf.init()初始化方法 

               >>> 初始化 graphics H/W ...,

               >>> 建立對象顯示設備HWComposer.cpp

               >>> 建立event線程

               >>> 初始化顯示設備

             >> 註冊ServiceManager、GPUService

             >> 運行SF.run()方法  (詳細處理合成圖像)

 

 

  SF的工做流程分析(實現圖像混合):

           > 在run方法中waitForEvent等待事件(MessagQueu.cpp),收到重繪消息後,將退出等待,交給onMessageReceivered去處理

           > handleMessageTransaction處理事務

              >> 有事務處理請求時,調用handleTransaction進行處理(getTransactionFlags)

             >> 調用handleTransactionLocked

             >> commitTransactionao提交事務

           > handleMessageInvalidateia調用handlePageFlip繪製

           > handleMessageRefresh合併和渲染

           > 完成後,線程繼續等待下一個invalidate消息

 

          (如下是深刻理解Android的講解,源碼爲2.2

           > 處理事務

                >> 有事務處理請求時,調用handleTransaction進行處理(getTransactionFlags)

             >> 調用handleTransactionLocked

             >> commitTransactionao提交事務

             > handlePageFlip繪製(Layer從FrontBuffer中取得新數據,並生成一張OpenGL中的紋理。如今Layer準備好了數據,下一步開始進行繪製)

             > handleRepaint對每一層進行重繪(顯示層的onDraw函數,使用OpenGL)

             > 繪製完圖後,unlockClient釋放以前佔着FrontBuffer的索引,調用各個顯示層的finishPageFlip函數

             > postFrameBuffer調用DisplayHardware.cpp的flip函數,flipg調用eglSwapBuffers函數,以完成FrameBuffer的apgeFlip操做,以後混合後的圖像就會傳遞到屏幕中顯示

 

 

  交互模塊:

    應用經過windowsmanager分配一個surface,須要分配顯示空間在上面進行繪圖,在圖形繪製完成後須要推送到surfaceflinger進行合成顯示。
   surfaceflinger做爲消費者,獲得一個要合成的圖形,在合成完畢後再將圖形釋放。

    大概流程:

    ->bufferqueue.cpp(../native/libs/gui庫

    -> composerService(單例模式)與SF創建bind鏈接

    -> SurfaceComposerClinet.cpp調用createaSurfce建立surface,返回surfaceControl

    -> 建立surface後在graphicBuffer.cpp(../native/libs/ui庫)分配共享內存

    -> 建立surface後,SF也對應一個layer,當上層layer調用刷新後,onFrameAvailable被調用,通知SF有layer更新 

 

  !!!初次接觸,翻閱《深刻理解Android》(2.2源碼)以及其餘的博客(Android6.0以上源碼)不少地方還不理解,因此有不正確的地方還請指正。

相關文章
相關標籤/搜索