Android4.4——SurfaceFlinger启动

        SurfaceFlinger是一项系统底层的服务,是负责UI方面的渲染的,与应用Application实时交互,实时刷新Surface,是与用户最直接打交道的一项服务。

        下面我们将分析SurfaceFlinger服务的启动过程。


        在system\core\rootdir\init.rc文件中,有这么段代码:

……
service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart media
    onrestart restart surfaceflinger
onrestart restart drm
……
service surfaceflinger /system/bin/surfaceflinger
    class main
    user system
    group graphics drmrpc
onrestart restart zygote
……
        SurfaceFlinger服务是在init过程中通过执行/system/bin/surfaceflinger这个bin文件启动,而在编译过程中通过编译frameworks/native/services/surfaceflinger该目录下的代码最终生成了surfaceflinger这个bin文件。
        好,下面来开始跟踪一下其中最终要的surfaceflinger服务的main函数。

Step 1、main()

在Android 4.4中,SurfaceFlinger的启动由frameworks/native/services/surfaceflinger/Main_surfaceflinger.cpp中的main函数启动。

int main(int argc, char** argv) {
    // When SF is launched in its own process, limit the number of
    // binder threads to 4.
    ProcessState::self()->setThreadPoolMaxThreadCount(4);

    // start the thread pool
    sp ps(ProcessState::self());
    ps->startThreadPool();

    // instantiate surfaceflinger
    sp flinger = new SurfaceFlinger(); //创建一个SurfaceFlinger对象

#if defined(HAVE_PTHREADS)
    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
#endif
    set_sched_policy(0, SP_FOREGROUND);

    // initialize before clients can connect
    flinger->init(); //初始化SurfaceFlinger

    // publish surface flinger
    sp sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);//将SrufaceFlinger加入服务

    // run in this thread
    flinger->run();//运行SurfaceFlinger服务

    return 0;
}

        这里创建了SurfaceFlinger对象,随后初始化该对象,并且以该对象作为参数,将SurfaceFlinger服务加入ServiceManager中。

接下来,来分步解析。


Step 2、new SurfaceFlinger()

        该代码在frameworks/native/services/surfaceflinger.cpp中。

SurfaceFlinger::SurfaceFlinger()
    :   BnSurfaceComposer(),//创建SurfaceComposer本地对象
        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),
        mDebugDisableTransformHint(0),
        mDebugInSwapBuffers(0),
        mLastSwapBufferTime(0),
        mDebugInTransaction(0),
        mLastTransactionTime(0),
        mBootFinished(false),
        mGpuTileRenderEnable(false),
        mPrimaryHWVsyncEnabled(false),
        mHWVsyncAvailable(false),
        mDaltonize(false)
{
    ALOGI("SurfaceFlinger is starting");

    // debugging stuff...
    char value[PROPERTY_VALUE_MAX];

    property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
    mGpuToCpuSupported = !atoi(value);

    property_get("debug.sf.showupdates", value, "0");
    mDebugRegion = atoi(value);

    property_get("debug.sf.ddms", value, "0");
    mDebugDDMS = atoi(value);
    if (mDebugDDMS) {
        if (!startDdmConnection()) {
            // start failed, and DDMS debugging not enabled
            mDebugDDMS = 0;
        }
    }
}


Step 2、SurfaceFlinger::OnFirstRef()

        由于flinger为sp强指针类型,当第一次被一个强指针引用时,就会执行SurfaceFlinger::OnFirstRef()函数。

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

        这里,mEventQueue是一个MessageQueue对象,是一个消息队列。定义的地方在SurfaceFlinger.h文件中。

    mutable MessageQueue mEventQueue;

        将SurfaceFlinger对象作为参数传入ini函数中,对MessageQueue初始化。将surfaceFlinger对象本神赋值给MessageQueue.mFlinger,也对MessageQueue中mHandler和mLooper进行赋值。


Step 3、MessageQueue::init

        代码位于frameworks/native/services/surfaceflinger/MessageQueue.cpp中。

void MessageQueue::init(const sp& flinger)
{
    mFlinger = flinger; 
    //创建主线程1 
    mLooper = new Looper(true);
    mHandler = new Handler(*this);
}
 
  
 
  
 
  
 
  
 
  
 
  

        将之前传入的SurfaceFlinger对象赋给MessageQueue的成员变量mFlinger,并且创建了消息队列的循环体Looper和事件处理器Handler。关于Looper和Handler,可以参考:http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html这个博客,里面讲的很是详细。

        MessageQueue::init函数创建了下图中的主线程1,Looper配合着Message、Handle、Thread、MessageQueue完成了太多的事情,在这里简单说就是它搞了一个睡眠等待事件,然后等着被唤醒。结合到SF中就是说,这里开了一个线程等待surface的刷新,而做出相关的操作。至于是怎么唤醒的可以参考这个连接的博文http://blog.csdn.net/broadview2006/article/details/8552148。

Step 4、SurfaceFlinger::init()

        在前面几步后,完成了SurfaceFlinger对象的创建过程后,需要对SurfaceFlinger对象进行初始化。

        本部分的代码位于frameworks/native/services/wurfaceflinger.cpp中。

void SurfaceFlinger::init() {

    status_t err;
    Mutex::Autolock _l(mStateLock);

    // initialize EGL for the default display
    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(mEGLDisplay, NULL, NULL);

    // Initialize the H/W composer object.  There may or may not be an
    // actual hardware composer underneath.
    mHwc = new HWComposer(this,
            *static_cast(this)); //创建HWComposer对象,通过HWComposer对象可以产生VSync同步信号。

    // 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);
    }

    // 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);

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

    // retrieve the EGL context that was selected/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 ; iisConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
            // All non-virtual displays are currently considered secure.
            bool isSecure = true;
            createBuiltinDisplayLocked(type);
            wp token = mBuiltinDisplays[i];

            sp bq = new BufferQueue(new GraphicBufferAlloc());
            sp fbs = new FramebufferSurface(*mHwc, i, bq);
            sp hw = new DisplayDevice(this,
                    type, allocateHwcDisplayId(type), isSecure, token,
                    fbs, bq,
                    mEGLConfig);
            if (i > DisplayDevice::DISPLAY_PRIMARY) {
                // FIXME: currently we don't get blank/unblank requests
                // for displays other than the main display, so we always
                // assume a connected display is unblanked.
                ALOGD("marking display %d as acquired/unblanked", i);
                hw->acquireScreen();
            }
            mDisplays.add(token, hw);
        }
    }

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

    // start the EventThread
    sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            vsyncPhaseOffsetNs, true);
    mEventThread = new EventThread(vsyncSrc);
    sp sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            sfVsyncPhaseOffsetNs, true);
    mSFEventThread = new EventThread(sfVsyncSrc);
    mEventQueue.setEventThread(mSFEventThread);

    mEventControlThread = new EventControlThread(this);
    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);

    // set a fake vsync period if there is no HWComposer
    if (mHwc->initCheck() != NO_ERROR) {
        mPrimaryDispSync.setPeriod(16666667);
    }

    // initialize our drawing state
    mDrawingState = mCurrentState;

    // set initial conditions (e.g. unblank default device)
    initializeDisplays();

    // start boot animation
    startBootAnim();
}
        在init的过程中,创建了下图中的线程3,其中的关键代码如下:

    // start the EventThread
    sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            vsyncPhaseOffsetNs, true);
    mEventThread = new EventThread(vsyncSrc);
    sp sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            sfVsyncPhaseOffsetNs, true);
    mSFEventThread = new EventThread(sfVsyncSrc);
    mEventQueue.setEventThread(mSFEventThread);

    mEventControlThread = new EventControlThread(this);
    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);

        这里分两个线路来说:

        1、EventThread继承自Thread线程类,Thread的基类中有RefBase,如下:

class VSyncSource : public virtual RefBase {
public:
    class Callback: public virtual RefBase {
    public:
        virtual ~Callback() {}
        virtual void onVSyncEvent(nsecs_t when) = 0;
    };

    virtual ~VSyncSource() {}
    virtual void setVSyncEnabled(bool enable) = 0;
    virtual void setCallback(const sp& callback) = 0;
};
class EventThread : public Thread, private VSyncSource::Callback {
    class Connection : public BnDisplayEventConnection {
    public:
        Connection(const sp& eventThread);
        status_t postEvent(const DisplayEventReceiver::Event& event);

        // count >= 1 : continuous event. count is the vsync rate
        // count == 0 : one-shot event that has not fired
        // count ==-1 : one-shot event that fired this round / disabled
        int32_t count;

    private:
        virtual ~Connection();
        virtual void onFirstRef();
        virtual sp getDataChannel() const;
        virtual void setVsyncRate(uint32_t count);
        virtual void requestNextVsync();    // asynchronous
        sp const mEventThread;
        sp const mChannel;
};

    …

};

         所以当EventThread定义的时候就会调用OnFirstRef()函数,这个函数中只有run()函数。 
  

void EventThread::onFirstRef() {
    run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}
        由于EventThread继承自Thread,所以在执行run函数之后,会执行EventThread::threadLoop()函数。

bool EventThread::threadLoop() {
    DisplayEventReceiver::Event event;
    Vector< sp > signalConnections;
    signalConnections = waitForEvent(&event);//等待Vsync事件

    // dispatch events to listeners...
    const size_t count = signalConnections.size();
    for (size_t i=0 ; i& conn(signalConnections[i]);
        // now see if we still need to report this event
        status_t err = conn->postEvent(event);//事件信息写入BitTuBe,也就是已建立连接的套接字队的一个套接字中,注册的接收端通过另一个套接字接收数据
        if (err == -EAGAIN || err == -EWOULDBLOCK) {
            // The destination doesn't accept events anymore, it's probably
            // full. For now, we just drop the events on the floor.
            // FIXME: Note that some events cannot be dropped and would have
            // to be re-sent later.
            // Right-now we don't have the ability to do this.
            ALOGW("EventThread: dropping event (%08x) for connection %p",
                    event.header.type, conn.get());
        } else if (err < 0) {
            // handle any other error on the pipe as fatal. the only
            // reasonable thing to do is to clean-up this connection.
            // The most common error we'll get here is -EPIPE.
            removeDisplayEventConnection(signalConnections[i]);
        }
    }
    return true;
}
         当客户端请求渲染Surface的时候,这里就会接收到Vsync事件,则waitForEvent函数将返回用于连接客户端的signalConnections的Connection列表。(以后研究) 
  

        如果收到一个Vsync事件,就会执行到conn->postEvent(event),该函数作用请看上面的注释。至此,EventThread线程发送了一个套接字信息。下面继续讲讲上面提到的注册的接收端。

        2、到底谁来接收套接字?

        在之前SurfaceFlinger::init函数中有这样一句代码:

mEventQueue.setEventThread(mSFEventThread);
        这个与pollOnce函数有关。

        setEventThread函数的具体实现如下。

void MessageQueue::setEventThread(const sp& eventThread)
{
    mEventThread = eventThread;
    mEvents = eventThread->createEventConnection();//创建一个到EventThread的连接
    mEventTube = mEvents->getDataChannel();//得到发送Vsync事件通知的BitTuBe
    mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT,
            MessageQueue::cb_eventReceiver, this);
}
        上面addFd函数的第一个参数是获取套接字队列中的信息,一旦有东西就会调用MessageQueue::cb_eventReceiver这个回调函数。

int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
    MessageQueue* queue = reinterpret_cast(data);
    return queue->eventReceiver(fd, events);//返回事件接收者
}
        根据套接字队列中的信息,得到事件队列,最后返回事件接收者。

int MessageQueue::eventReceiver(int fd, int events) {
    ssize_t n;
    DisplayEventReceiver::Event buffer[8];
    while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
        for (int i=0 ; idispatchInvalidate();
#else
                mHandler->dispatchRefresh();
#endif
                break;
            }
        }
    }
    return 1;
}
        这里主线程一直在获取事件,一旦事件类型为DISPLAY_EVENT_VSYNC,就会执行dispatchInvalidate或者dispatchRefresh函数。有关Vsync,之后再详细研究,先看看这篇博客: http://blog.csdn.net/broadview2006/article/details/8541727。

        dispatchInvalidate请看看这篇博客:http://blog.csdn.net/w401229755/article/details/38224481的后半段。这里只看dispatchRefresh函数。

void MessageQueue::Handler::dispatchRefresh() {
    if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
        mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
    }
}
        这里发送了REFRESH消息,在SurfaceFlinger::run函数中创建了下图中的线程2后在一直睡眠等待消息,其中的pollInner函数的handleMessage是具体处理消息的地方,具体分析请参照Step 8和Step 9。

Step 5、SurfaceFlinger::run()

        在创建初始化SurfaceFlinger对象后,随后调用SurfaceFlinger的成员函数run()运行SurfaceFlinger服务。

        本代码位于frameworks/native/services/surfaceflinger.cpp中。

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

        这里创建了下图中的线程2。

        由于SurfaceFlinger服务需要时刻运行,实时绘制,所以不能理解使用do...while循环无限调用SurfaceFlinger成员函数waitForEvent。


Step 6 、SurfaceFlinger::waitForEvent()
本代码位于frameworks/native/services/surfaceflinger.cpp中。

void SurfaceFlinger::waitForEvent() {
    mEventQueue.waitMessage();
}


Step 7、MessageQueue::waitMessage()

        本代码位于frameworks/native/services/MessageQueue.cpp中。

void MessageQueue::waitMessage() {
    do {
        IPCThreadState::self()->flushCommands();
        int32_t ret = mLooper->pollOnce(-1);
        switch (ret) {
            case ALOOPER_POLL_WAKE:
            case ALOOPER_POLL_CALLBACK:
                continue;
            case ALOOPER_POLL_ERROR:
                ALOGE("ALOOPER_POLL_ERROR");
            case ALOOPER_POLL_TIMEOUT:
                // timeout (should not happen)
                continue;
            default:
                // should not happen
                ALOGE("Looper::pollOnce() returned unknown status %d", ret);
                continue;
        }
    } while (true);
}
        程序进入了一个死循环,即使mLooper->pollOnce的返回结果为ALOOPER_POLL_TIMEOUT也不会退出。Android对于处理一些严重的系统错误,采取的是一种"Let it be"的态度。

Step 8、Looper::pollOnce()
        mLooper->pollOnce函数的代码位于frameworks/base/libs/utils/Looper.cpp中。

int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    int result = 0;
    for (;;) {
        while (mResponseIndex < mResponses.size()) {
            const Response& response = mResponses.itemAt(mResponseIndex++);
            int ident = response.request.ident;
            if (ident >= 0) {
                int fd = response.request.fd;
                int events = response.events;
                void* data = response.request.data;
                if (outFd != NULL) *outFd = fd;
                if (outEvents != NULL) *outEvents = events;
                if (outData != NULL) *outData = data;
                return ident;
            }
        }

        if (result != 0) {
            if (outFd != NULL) *outFd = 0;
            if (outEvents != NULL) *outEvents = 0;
            if (outData != NULL) *outData = NULL;
            return result;
        }

        result = pollInner(timeoutMillis);
    }
}


Step 9、Looper::pollInner

int Looper::pollInner(int timeoutMillis) {

    // Adjust the timeout based on when the next message is due.
    if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
        if (messageTimeoutMillis >= 0
                && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
            timeoutMillis = messageTimeoutMillis;
        }
    }

    // Poll.
    int result = ALOOPER_POLL_WAKE;
    mResponses.clear();
    mResponseIndex = 0;

    // We are about to idle.
    mIdling = true;

    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

    // No longer idling.
    mIdling = false;

    // Acquire lock.
    mLock.lock();

    // Check for poll error.
    if (eventCount < 0) {
        if (errno == EINTR) {
            goto Done;
        }
        result = ALOOPER_POLL_ERROR;
        goto Done;
    }

    // Check for poll timeout.
    if (eventCount == 0) {
        result = ALOOPER_POLL_TIMEOUT;
        goto Done;
    }

    // Handle all events.
    for (int i = 0; i < eventCount; i++) {
        int fd = eventItems[i].data.fd;
        uint32_t epollEvents = eventItems[i].events;
        if (fd == mWakeReadPipeFd) {
            if (epollEvents & EPOLLIN) {
                awoken();
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
            }
        } else {
            ssize_t requestIndex = mRequests.indexOfKey(fd);
            if (requestIndex >= 0) {
                int events = 0;
                if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
                if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
                if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
                if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
                pushResponse(events, mRequests.valueAt(requestIndex));
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
                        "no longer registered.", epollEvents, fd);
            }
        }
    }
Done: ;

    // Invoke pending message callbacks.
    mNextMessageUptime = LLONG_MAX;
    while (mMessageEnvelopes.size() != 0) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
        if (messageEnvelope.uptime <= now) {
            // Remove the envelope from the list.
            // We keep a strong reference to the handler until the call to handleMessage
            // finishes.  Then we drop it so that the handler can be deleted *before*
            // we reacquire our lock.
            { // obtain handler
                sp handler = messageEnvelope.handler;
                Message message = messageEnvelope.message;
                mMessageEnvelopes.removeAt(0);
                mSendingMessage = true;
                mLock.unlock();

                handler->handleMessage(message);
            } // release handler

            mLock.lock();
            mSendingMessage = false;
            result = ALOOPER_POLL_CALLBACK;
        } else {
            // The last message left at the head of the queue determines the next wakeup time.
            mNextMessageUptime = messageEnvelope.uptime;
            break;
        }
    }

    // Release lock.
    mLock.unlock();

    // Invoke all response callbacks.
    for (size_t i = 0; i < mResponses.size(); i++) {
        Response& response = mResponses.editItemAt(i);
        if (response.request.ident == ALOOPER_POLL_CALLBACK) {
            int fd = response.request.fd;
            int events = response.events;
            void* data = response.request.data;

            int callbackResult = response.request.callback->handleEvent(fd, events, data);
            if (callbackResult == 0) {
                removeFd(fd);
            }
            // Clear the callback reference in the response structure promptly because we
            // will not clear the response vector itself until the next poll.
            response.request.callback.clear();
            result = ALOOPER_POLL_CALLBACK;
        }
    }
    return result;
}

        pollOnce与pollInner的关系,请看看这篇博客:http://blog.csdn.net/broadview2006/article/details/8541727。

        在Looper::pollInner函数中内部调用MessageQueue::mHandler处理消息?????

        PS:(下面一段摘自大侠林学森的博客文章——Android显示系统之SurfaceFlinger(一))

这样子就构建了一个简洁而又完整的循环消息处理框架,SurfaceFlinger就是基于这个框架完成来自系统中各个程序的显示请求的。大家可能会有疑问,mHandler是由MessageQueue直接通过new Handler()生成的,这样的话如何能处理特定的SurfaceFlinger消息请求呢?个人感觉有这个困惑是由于Handler类取名不当引起的。实际上此Handler并非我们经常看到的那个Handler,这里的Handler是MessageQueue中自定义的一个事件处理器,也就是说它是专门为SurfaceFlinger设计的。


Step 10、MessageQueue::Handler::handleMessage()

代码位于frameworks/native/services/surfaceflinger/MessageQueue.cpp中。

void MessageQueue::Handler::handleMessage(const Message& message) {
    switch (message.what) {
        case INVALIDATE:
            android_atomic_and(~eventMaskInvalidate, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
        case REFRESH:
            android_atomic_and(~eventMaskRefresh, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
        case TRANSACTION:
            android_atomic_and(~eventMaskTransaction, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
    }
}
        当mHandler收到INVALIDATE、REFRESH和TRANSACTION消息后,又会回调SurfaceFlinger::onMessageReceived函数。这样绕了一圈友重新返回到了SurfaceFlinger中。


        附上一张网上大牛画的一张有关SurfaceFlinger的图,逻辑很清晰。

Android4.4——SurfaceFlinger启动_第1张图片










你可能感兴趣的:(Android,Framework)