android graphic(3)—surfaceflinger的启动流程

http://blog.csdn.net/lewif/article/details/50559904

目录(?)[+]


这篇文章只分析SF消息驱动流程的建立,不涉及具体的功能实现,关于SFHWC如何交互后续分析,基于Android 4.4,以下将surfaceflinger简称为SF

如何启动

android 4.4SFinit.rc中启动,如下所示:

service surfaceflinger /system/bin/surfaceflinger

    class main

    user system

    group graphics drmrpc

    onrestartrestart zygote

可以看出,SF/system/bin/下的一个应用程序,在makefile中搜索LOCAL_MODULE:=surfaceflinger即可找到具体的makefile和代码,

#首先是个SF的动态库

LOCAL_MODULE:=libsurfaceflinger

 

include$(BUILD_SHARED_LIBRARY)

 

# 其次是surfaceflinger,

LOCAL_SRC_FILES:= \

   main_surfaceflinger.cpp

 

LOCAL_SHARED_LIBRARIES:= \

   libsurfaceflinger \

    libcutils \

    liblog \

    libbinder \

    libutils

 

LOCAL_MODULE:= surfaceflinger

 

include$(BUILD_EXECUTABLE)

从上面makefile就能看出来,首先有个动态库libsurfaceflinger.so,然后SF只是对库的一个封装调用,多了一个main_surfaceflinger.cpp,里面仅有个main函数,下面展开。

执行流程

只关注SF流程,不关注binder线程等。

int main(int argc, char** argv) {

    // When SF is launched in its ownprocess, limit the number of

    // binder threads to 4.

    ProcessState::self()->setThreadPoolMaxThreadCount(4);

 

    // start the thread pool

    sp<ProcessState> ps(ProcessState::self());

    ps->startThreadPool();

 

    // instantiate surfaceflinger

    //

    sp<SurfaceFlinger> flinger =newSurfaceFlinger();

 

#ifdefined(HAVE_PTHREADS)

   setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);

#endif

   set_sched_policy(0, SP_FOREGROUND);

 

    // initialize before clients can connect

    //

    flinger->init();

 

    // publish surface flinger

    sp<IServiceManager>sm(defaultServiceManager());

    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);

 

    // run in this thread

    //

    flinger->run();

 

    return0;

}

main函数主要的内容包含三方面,逐步分析。

new SurfaceFlinger

首先,new了一个SF,并使用sp指针,所以我们需要关注SF类中是否实现了onFirstRef()函数。

sp<SurfaceFlinger>flinger = new SurfaceFlinger();

构造函数中初始化一些值,

SurfaceFlinger::SurfaceFlinger()

    :   BnSurfaceComposer(),

       mTransactionFlags(0),

       mTransactionPending(false),

        mAnimTransactionPending(false),

       mLayersRemoved(false),

       mRepaintEverything(0),

       mRenderEngine(NULL),

       mBootTime(systemTime()),

       mVisibleRegionsDirty(false),

       mHwWorkListDirty(false),

        mAnimCompositionPending(false),

       mDebugRegion(0),

        mDebugDDMS(0),

       mDebugDisableHWC(0),

        mDebugFps(0),

       mDebugDisableTransformHint(0),

       mDebugInSwapBuffers(0),

       mLastSwapBufferTime(0),

       mDebugInTransaction(0),

       mLastTransactionTime(0),

       mBootFinished(false),

       mPrimaryHWVsyncEnabled(false),

       mHWVsyncAvailable(false),

        mDaltonize(false)

{

//一些调试的变量等

 

}

SF确实实现了onFirstRef()函数,

//mutableMessageQueue mEventQueue;

voidSurfaceFlinger::onFirstRef()

{

   mEventQueue.init(this);

}

调用MessageQueueinit,在MessageQueue中建了一个LooperHandler,注意不是Java中的,native实现的。 到后面就可以看到SF的核心就是接收消息,处理消息。

voidMessageQueue::init(constsp<SurfaceFlinger>& flinger)

{

    mFlinger =flinger;

    mLooper = new Looper(true);

    mHandler = new Handler(*this);

}

init函数

init中主要创建了OpenGL ES环境,对显示器的初始化等。

voidSurfaceFlinger::init() {

    ALOGI(  "SurfaceFlinger's main thread ready to run. "

            "Initializing graphics H/W...");

 

    status_t err;

    Mutex::Autolock_l(mStateLock);

 

    // initialize EGL for the defaultdisplay

    mEGLDisplay =eglGetDisplay(EGL_DEFAULT_DISPLAY);

   eglInitialize(mEGLDisplay, NULL, NULL);

 

    // Initialize the H/W composerobject.  There may or may not be an

    // actual hardware composer underneath.

    mHwc = new HWComposer(this,

            *static_cast<HWComposer::EventHandler*>(this));

 

    // First try to get an ES2 config

    err =selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT,

           &mEGLConfig);

 

    if (err !=NO_ERROR) {

        // If ES2 fails, try ES1

        err =selectEGLConfig(mEGLDisplay, mHwc->getVisualID(),

               EGL_OPENGL_ES_BIT, &mEGLConfig);

    }

 

    if (err !=NO_ERROR) {

        // still didn't work, probably becausewe're on the emulator...

        // try a simplified query

        ALOGW("no suitable EGLConfig found,trying a simpler query");

        err =selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig);

    }

 

    if (err !=NO_ERROR) {

        // this EGL is too lame for android

       LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");

    }

 

    // print some debugging info

    EGLint r,g,b,a;

   eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_RED_SIZE,   &r);

   eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_GREEN_SIZE, &g);

   eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_BLUE_SIZE,  &b);

    eglGetConfigAttrib(mEGLDisplay,mEGLConfig, EGL_ALPHA_SIZE, &a);

    ALOGI("EGL informations:");

    ALOGI("vendor    : %s",eglQueryString(mEGLDisplay, EGL_VENDOR));

    ALOGI("version   : %s",eglQueryString(mEGLDisplay, EGL_VERSION));

    ALOGI("extensions: %s",eglQueryString(mEGLDisplay, EGL_EXTENSIONS));

    ALOGI("Client API: %s",eglQueryString(mEGLDisplay, EGL_CLIENT_APIS)?:"Not Supported");

    ALOGI("EGLSurface: %d-%d-%d-%d,config=%p", r, g, b, a, mEGLConfig);

 

    // get a RenderEngine for the givendisplay / config (can't fail)

    mRenderEngine =RenderEngine::create(mEGLDisplay, mEGLConfig);

 

    // retrieve the EGL context that wasselected/created

    mEGLContext =mRenderEngine->getEGLContext();

 

    // figure out which format we got

    eglGetConfigAttrib(mEGLDisplay,mEGLConfig,

           EGL_NATIVE_VISUAL_ID, &mEGLNativeVisualId);

 

   LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,

            "couldn't create EGLContext");

 

    // initialize our non-virtual displays

    for (size_t i=0 ;i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {

       DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);

        // set-up the displays that are alreadyconnected

        if(mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {

            // All non-virtual displays arecurrently considered secure.

            bool isSecure = true;

           createBuiltinDisplayLocked(type);

           wp<IBinder> token = mBuiltinDisplays[i];

 

           sp<BufferQueue> bq = new BufferQueue(newGraphicBufferAlloc());

           sp<FramebufferSurface> fbs = newFramebufferSurface(*mHwc, i, bq);

           sp<DisplayDevice> hw = new DisplayDevice(this,

                   type, allocateHwcDisplayId(type), isSecure, token,

                    fbs, bq,

                   mEGLConfig);

            if (i >DisplayDevice::DISPLAY_PRIMARY) {

                // FIXME: currently we don't getblank/unblank requests

                // for displays other than the maindisplay, so we always

                // assume a connected display is unblanked.

               ALOGD("markingdisplay %d as acquired/unblanked", i);

               hw->acquireScreen();

            }

           mDisplays.add(token, hw);

        }

    }

 

    // make the GLContext current so that wecan create textures when creating Layers

    // (which may happens before we rendersomething)

   getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);

 

    // start the EventThread

   sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,

           vsyncPhaseOffsetNs, true);

    mEventThread = newEventThread(vsyncSrc);

   sp<VSyncSource> sfVsyncSrc = newDispSyncSource(&mPrimaryDispSync,

           sfVsyncPhaseOffsetNs, false);

    mSFEventThread= new EventThread(sfVsyncSrc);

   mEventQueue.setEventThread(mSFEventThread);

 

   mEventControlThread = new EventControlThread(this);

   mEventControlThread->run("EventControl",PRIORITY_URGENT_DISPLAY);

 

    // set a fake vsync period if there isno HWComposer

    if(mHwc->initCheck() != NO_ERROR) {

       mPrimaryDispSync.setPeriod(16666667);

    }

 

    // initialize our drawing state

    mDrawingState =mCurrentState;

 

    // set initial conditions (e.g. unblankdefault device)

   initializeDisplays();

 

    // start boot animation

   startBootAnim();

}

最后部分启动了开机动画程序bootanim,肯定是SF启动起来后才能去执行绘画相关的进程。

void SurfaceFlinger::startBootAnim() {

    // start boot animation

    property_set("service.bootanim.exit", "0");

    property_set("ctl.start", "bootanim");

}

run函数

run函数非常简单,但却是SF的核心,是个while循环,循环处理消息等。

void SurfaceFlinger::run() {

    do {

       waitForEvent();

    } while (true);

}

void SurfaceFlinger::waitForEvent() {

    mEventQueue.waitMessage();

}

可以看到,接收处理消息的关键在mLooper->pollOnce(-1);

voidMessageQueue::waitMessage(){

    do {

        IPCThreadState::self()->flushCommands();

        int32_t ret= mLooper->pollOnce(-1);

        switch (ret) {

            caseALOOPER_POLL_WAKE:

            caseALOOPER_POLL_CALLBACK:

                continue;

            caseALOOPER_POLL_ERROR:

               ALOGE("ALOOPER_POLL_ERROR");

            caseALOOPER_POLL_TIMEOUT:

                // timeout (shouldnot happen)

                continue;

            default:

                // should not happen

               ALOGE("Looper::pollOnce()returned unknown status %d", ret);

                continue;

        }

    } while (true);

}

SF发消息

首先关注如何给SF发送消息,以Client创建surface为例,

status_t Client::createSurface(

        const String8&name,

        uint32_t w,uint32_t h, PixelFormat format, uint32_t flags,

       sp<IBinder>* handle,

        sp<IGraphicBufferProducer>*gbp)

{

    /*

     * createSurface must be called from the GLthread so that it can

     * have access to the GL context.

     */

 

    classMessageCreateLayer : public MessageBase {

       SurfaceFlinger* flinger;

        Client*client;

       sp<IBinder>* handle;

       sp<IGraphicBufferProducer>* gbp;

        status_tresult;

        const String8&name;

        uint32_t w,h;

        PixelFormatformat;

        uint32_tflags;

    public:

        MessageCreateLayer(SurfaceFlinger*flinger,

                const String8&name, Client* client,

               uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,

               sp<IBinder>* handle,

               sp<IGraphicBufferProducer>* gbp)

            : flinger(flinger), client(client),

              handle(handle), gbp(gbp),

              name(name), w(w), h(h), format(format), flags(flags) {

        }

        status_tgetResult() const { return result; }

        //handler是执行消息动作的地方,

        virtualbool handler() {

            result= flinger->createLayer(name, client, w, h, format, flags,

                   handle, gbp);

            returntrue;

        }

    };

    //首先封装消息

   sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),

            name, this, w, h, format,flags, handle, gbp);

    //调用SFpostMessageSync发送同步消息

   mFlinger->postMessageSync(msg);

    returnstatic_cast<MessageCreateLayer*>( msg.get())->getResult();

}

MessageBase就是封装了类似于一个Handler,里面有个Barrier,我们能够猜到,这个Barrier 肯定是用来进行同步发送消息的,利用Barrier 去等待”wait”

class MessageBase : public MessageHandler

{

public:

    MessageBase();

 

    // return true if message has a handler

    virtualbool handler() = 0;

 

    // waits for the handler to be processed

    void wait() const {barrier.wait(); }

 

protected:

    virtual ~MessageBase();

 

private:

    virtualvoidhandleMessage(const Message&message);

 

    mutable Barrierbarrier;

};

MessageBasehandleMessage函数,可以看到MessageBasehandler()函数是真正消息处理的地方,执行完成后,调用barrier.open();,打开barrier,这样调用barrier.wait()的地方就能退出了。

voidMessageBase::handleMessage(const Message&) {

    this->handler();

    barrier.open();

};

接着分析mFlinger->postMessageSync(msg);,这是给SF发同步消息的入口,当然也可以发异步消息,实现是类似的,

        status_tSurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,

               nsecs_t reltime, uint32_t flags) {

            //mEventQueue,即MessageQueue中发送消息

           status_t res = mEventQueue.postMessage(msg,reltime);

            //这里等着,同步就在同步函数中等着

            if (res == NO_ERROR) {

                msg->wait();

            }

            return res;

        }

可以看到在同步发送消息中,barrierpostMessageSync函数中一直等着呢(wait),等待SF调用handleMessage()函数去将barrier这个栅栏打开(open)

SF处理消息

上面提到,处理消息的关键就在mLooper->pollOnce(-1);函数中,而pollOnce又会调用pollInner,只摘取了处理消息的一段,

intLooper::pollInner(int timeoutMillis){

  // Invoke pending message callbacks.

   mNextMessageUptime = LLONG_MAX;

    while(mMessageEnvelopes.size() != 0) {

        nsecs_t now= systemTime(SYSTEM_TIME_MONOTONIC);

        constMessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);

        if (messageEnvelope.uptime <= now) {

            // Remove the envelope from the list.

            // We keep a strong reference to thehandler until the call to handleMessage

            // finishes.  Then we drop it so that the handler can bedeleted *before*

            // we reacquire our lock.

            { // obtain handler

               sp<MessageHandler> handler = messageEnvelope.handler;

               Message message = messageEnvelope.message;

                //把头删除啊

               mMessageEnvelopes.removeAt(0);

               mSendingMessage = true;

               mLock.unlock();

 

#ifDEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS

               ALOGD("%p ~pollOnce - sending message: handler=%p, what=%d",

                       this, handler.get(),message.what);

#endif         

                //处理消息啊

               handler->handleMessage(message);

            } // release handler

 

            mLock.lock();

           mSendingMessage = false;

            result= ALOOPER_POLL_CALLBACK;

        } else {

            // The last message left at the head ofthe queue determines the next wakeup time.

           mNextMessageUptime = messageEnvelope.uptime;

            break;

        }

    }

}

从上面代码可以看到,发给SF的消息被封装在MessageEnvelope结构中,SF一直在mMessageEnvelopes队列中从头部取出消息,然后执行,即handler->handleMessage(message);

voidMessageBase::handleMessage(const Message&) {

    this->handler();

    //打开栅栏

    barrier.open();

};

调用handleMessage执行handler(),所以SF创建Surface的核心代码就是SFcreateLayer函数,

            result =flinger->createLayer(name, client, w, h, format, flags,

                   handle, gbp);

执行完成后,打开barrier

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值