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

来源:互联网 发布:财务尽调 知乎 编辑:程序博客网 时间:2024/05/18 03:15

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

目录(?)[+]

  • 如何启动
  • 执行流程
    • new SurfaceFlinger
    • init函数
    • run函数
      • SF发消息
      • SF处理消息

这篇文章只分析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:

                // shouldnot 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
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 桥梁梁片强度达不到设计要求怎么办 新车交车检验表客户没签字怎么办 中铁快运职工拒绝提货要怎么办 奇瑞a3暖风水箱爆了怎么办 别人挖鱼塘占了我的山土怎么办 自己的鱼塘让别人强行占住了怎么办 公路扩路占地占了鱼塘怎么办? 玉米皮编垫子编好后玉米绳怎么办 入户门门框未预留纱窗位怎么办 门和墙有2cm缝隙怎么办 支座预埋钢板忘记埋了怎么办 做完线雕一边紧一边松怎么办 卖家把没发货的填写了单号怎么办 买的人民币白银亏了好多钱怎么办 带控制线的三相四线开关怎么办 覆膜除尘布袋风拉不动怎么办 家里装修把暖气管道打破了怎么办 冷水管与热水管接错了怎么办 磨砂皮的鞋子打湿变硬了怎么办 等离子淡化热处理层渗不够厚怎么办 寄快递快递公司把东西弄坏了怎么办 寄美国的快递客人拒绝清关怎么办 国际e邮宝几天没物流信息了怎么办 石家庄小学网上报名填错了怎么办 去医院看病不知道挂什么科怎么办 深水井深水泵埋了2米怎么办 请问我捡的手机不是我的指纹怎么办 宝宝把塑料子弹塞到了鼻子里怎么办 坐便池上面的小孔不出水怎么办 还没离职已经找好工作怎么办 因火车晚点而耽误下趟火车怎么办 在广州坐的士丢了东西怎么办 找兼职的话他要求交押金怎么办 08vip不给提现了怎么办 点击订阅号所收到内容字太大怎么办 我的小叶栀子花老是黄叶该怎么办? 联币金融倒闭了我投资的钱怎么办 新单位交养老保险不接收档案怎么办 高铁发车十小时没赶上怎么办 饿了么被阿里收购员工怎么办? 爱疯4s密码忘了怎么办