android P Choreographer与SurfaceFlinger

前言

SurfaceFlinger和Choreographer是构成Android图形系统的主要部分,它们都是VSYNC信号的订阅者;SurfaceFlinger将接受到的不同数据源整合并,最终更新到帧缓冲以便显示;而Choreographer最终post给ViewRootImpl进行界面view的measure及draw等。

一、VSYNC的产生与分发
不管以何种方式启动SurfaceFlinger,创建SurfaceFlinger的实例之后都会调用init方法:

1. SurfaceFlinger.cpp

// Do not call property_set on main thread which will be blocked by init

// Use StartPropertySetThread instead.

void SurfaceFlinger::init() {

    ...
    Mutex::Autolock _l(mStateLock);
    // start the EventThread
    mScheduler =
            getFactory().createScheduler([this](bool enabled) { setVsyncEnabled(enabled); },
                                        mRefreshRateConfigs);
    auto resyncCallback =
            mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
    mAppConnectionHandle =
            mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
                                        resyncCallback,
                                        impl::EventThread::InterceptVSyncsCallback());
    mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),
                                                      resyncCallback, [this](nsecs_t timestamp) {
                                                          mInterceptor->saveVSyncEvent(timestamp);
                                                      });
    mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
    mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
                                          mSfConnectionHandle.get());
    mRegionSamplingThread =
            new RegionSamplingThread(*this, *mScheduler,
                                    RegionSamplingThread::EnvironmentTimingTunables());
    ...
    // Get a RenderEngine for the given display / config (can't fail)
    int32_t renderEngineFeature = 0;
    renderEngineFeature |= (useColorManagement ?
                            renderengine::RenderEngine::USE_COLOR_MANAGEMENT : 0);
    renderEngineFeature |= (useContextPriority ?
                            renderengine::RenderEngine::USE_HIGH_PRIORITY_CONTEXT : 0);
    {
        using vendor::display::config::V1_7::IDisplayConfig;
            android::sp disp_config_v1_7 = IDisplayConfig::getService();
        if (disp_config_v1_7 != NULL) {
            disp_config_v1_7->getDebugProperty("protected_client_composition",
                [&] (const ::android::hardware::hidl_string& value, int32_t error) {
                    if (error == 0) {
                        renderEngineFeature |= atoi(value.c_str()) ?
                            renderengine::RenderEngine::ENABLE_PROTECTED_CONTEXT : 0;
                    }
            });
        }
    }
    // TODO(b/77156734): We need to stop casting and use HAL types when possible.
    // Sending maxFrameBufferAcquiredBuffers as the cache size is tightly tuned to single-display.
    mCompositionEngine->setRenderEngine(
            renderengine::RenderEngine::create(static_cast(defaultCompositionPixelFormat),
                                              renderEngineFeature, maxFrameBufferAcquiredBuffers));
    LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
            "Starting with vr flinger active is not currently supported.");
    mCompositionEngine->setHwComposer(getFactory().createHWComposer(getBE().mHwcServiceName));
    mCompositionEngine->getHwComposer().registerCallback(this, getBE().mComposerSequenceId);
    // Process any initial hotplug and resulting display changes.
    processDisplayHotplugEventsLocked();
    const auto display = getDefaultDisplayDeviceLocked();
    LOG_ALWAYS_FATAL_IF(!display, "Missing internal display after registering composer callback.");
    LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(*display->getId()),
                        "Internal display is disconnected.");
    if (useVrFlinger) {
        auto vrFlingerRequestDisplayCallback = [this](bool requestDisplay) {
            // This callback is called from the vr flinger dispatch thread. We
            // need to call signalTransaction(), which requires holding
            // mStateLock when we're not on the main thread. Acquiring
            // mStateLock from the vr flinger dispatch thread might trigger a
            // deadlock in surface flinger (see b/66916578), so post a message
            // to be handled on the main thread instead.
            postMessageAsync(new LambdaMessage([=] {
                ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
                mVrFlingerRequestsDisplay = requestDisplay;
                signalTransaction();
            }));
        };
        mVrFlinger = dvr::VrFlinger::Create(getHwComposer().getComposer(),
                                            getHwComposer()
                                                    .fromPhysicalDisplayId(*display->getId())
                                                    .value_or(0),
                                            vrFlingerRequestDisplayCallback);
        if (!mVrFlinger) {
            ALOGE("Failed to start vrflinger");
        }
    }
    // initialize our drawing state
    mDrawingState = mCurrentState;
    // set initial conditions (e.g. unblank default device)
    initializeDisplays();
    getRenderEngine().primeCache();
    // Inform native graphics APIs whether the present timestamp is supported:
    const bool presentFenceReliable =
            !getHwComposer().hasCapability(HWC2::Capability::PresentFenceIsNotReliable);
    mStartPropertySetThread = getFactory().createStartPropertySetThread(presentFenceReliable);
    if (mStartPropertySetThread->Start() != NO_ERROR) {
        ALOGE("Run StartPropertySetThread failed!");
    }
    mScheduler->setChangeRefreshRateCallback(
            [this](RefreshRateType type, Scheduler::ConfigEvent event) {
                Mutex::Autolock lock(mStateLock);
                setRefreshRateTo(type, event);
            });
    mScheduler->setGetVsyncPeriodCallback([this] {
        Mutex::Autolock lock(mStateLock);
        return getVsyncPeriod();
    });
    mRefreshRateConfigs.populate(getHwComposer().getConfigs(*display->getId()));
    mRefreshRateStats.setConfigMode(getHwComposer().getActiveConfigIndex(*display->getId()));
    ALOGV("Done initializing");
}
2. SurfaceFlinger.h
    std::unique_ptr mScheduler;
    sp mAppConnectionHandle;
    sp mSfConnectionHandle;


3. Scheduler.h
    // Connections are stored in a map  for easy retrieval.
    std::unordered_map> mConnections;
    ...
    /* The scheduler handle is a BBinder object passed to the client from which we can extract
    * an ID for subsequent operations.
    */
    class ConnectionHandle : public BBinder {
    public:
        ConnectionHandle(int64_t id) : id(id) {}
        ~ConnectionHandle() = default;
        const int64_t id;
    };

    class Connection {
    public:
        Connection(sp handle, sp eventConnection,
                  std::unique_ptr eventThread)
              : handle(handle), eventConnection(eventConnection), thread(std::move(eventThread)) {}
        ~Connection() = default;
        sp handle;
        sp eventConnection;
        const std::unique_ptr thread;
    };


4. Scheduler.cpp
sp Scheduler::createConnection(
        const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    const int64_t id = sNextId++;
    ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
    //由第一个参数可以,总共生成两个EventThread对象,分别代表着"app"、"sf"。
    std::unique_ptr eventThread =
            makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
                            std::move(interceptCallback));
    auto eventThreadConnection =
            createConnectionInternal(eventThread.get(), std::move(resyncCallback));
    //此处以id为key值,value为Connection 加入到集合mConnections中
    //Connection是Scheduler的内部类
    mConnections.emplace(id,
                        std::make_unique(new ConnectionHandle(id),
                                                      eventThreadConnection,
                                                      std::move(eventThread)));
    return mConnections[id]->handle;
}

std::unique_ptr Scheduler::makeEventThread(
        const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    std::unique_ptr eventThreadSource =
            std::make_unique(dispSync, phaseOffsetNs, true, connectionName);
    //DispSyncSource持有DispSync、且DispSyncSource继承自VSyncSource
    //EventThread持有DispSyncSource
    return std::make_unique(std::move(eventThreadSource),
                                              std::move(interceptCallback), connectionName);

}

init方法中会实例化两个ConnectionHandle:mAppConnectionHandle、mSfConnectionHandle。以mAppConnectionHandle为例深入分析其具体结构及获取过程。ConnectionHandle属于Scheduler的内部类,继承自BBinder,即可以跨进程通信。
mAppConnectionHandle所持有的EventThread是Choreographer所代表App层的远程SOCKET服务端,mSfConnectionHandle所持有的EventThread则对应着SurfaceFlinger自身的VSYNC处理。它们都通过各自的DispSyncSource持有mPrimaryDispSync。
mPrimaryDispSync是DispSync的实例,内部持有一个DispSyncThread。EventThread在有客户端成功订阅VSYNC后,通过DispSyncSource的setVSyncEnabled方法调用DispSync的addEventListener方法,将mPhaseOffset和callback传递DispSync。
 

DispSyncSource.cpp
void DispSyncSource::setVSyncEnabled(bool enable) {
    std::lock_guard lock(mVsyncMutex);
    if (enable) {
        status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
                                                  static_cast(this),
                                                  mLastCallbackTime);
        if (err != NO_ERROR) {
            ALOGE("error registering vsync callback: %s (%d)", strerror(-err), err);
        }
        // ATRACE_INT(mVsyncOnLabel.c_str(), 1);
    } else {
        status_t err = mDispSync->removeEventListener(static_cast(this),
                                                      &mLastCallbackTime);
        if (err != NO_ERROR) {
            ALOGE("error unregistering vsync callback: %s (%d)", strerror(-err), err);
        }
        // ATRACE_INT(mVsyncOnLabel.c_str(), 0);
    }
    mEnabled = enable;
}

DispSync则通过这个offset和屏幕刷新周期period,依靠DispSyncThread线程控制着回调调用的时间,最终通过SurfaceFlinger的onDispSyncEvent方法调用到EventThread的onVSyncEvent方法。
 

1. DispSyncSource.cpp
    void DispSyncSource::setVSyncEnabled(bool enable) {
    std::lock_guard lock(mVsyncMutex);
    if (enable) {
        status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
                                                  static_cast(this),
                                                  mLastCallbackTime);
        if (err != NO_ERROR) {
            ALOGE("error registering vsync callback: %s (%d)", strerror(-err), err);
        }
        // ATRACE_INT(mVsyncOnLabel.c_str(), 1);
    } else {
        status_t err = mDispSync->removeEventListener(static_cast(this),
                                                      &mLastCallbackTime);
        if (err != NO_ERROR) {
            ALOGE("error unregistering vsync callback: %s (%d)", strerror(-err), err);
        }
        // ATRACE_INT(mVsyncOnLabel.c_str(), 0);
    }
    mEnabled = enable;
}

2. DispSync.cpp
    status_t DispSync::addEventListener(const char* name, nsecs_t phase, Callback* callback,
                                    nsecs_t lastCallbackTime) {
    Mutex::Autolock lock(mMutex);
    return mThread->addEventListener(name, phase, callback, lastCallbackTime);
}

3. DispSync.DispSyncThread
    //DispSyncThread继承自Thread
    status_t addEventListener(const char* name, nsecs_t phase, DispSync::Callback* callback,
                              nsecs_t lastCallbackTime) {
        if (mTraceDetailedInfo) ATRACE_CALL();
        Mutex::Autolock lock(mMutex);
        for (size_t i = 0; i < mEventListeners.size(); i++) {
            if (mEventListeners[i].mCallback == callback) {
                return BAD_VALUE;
            }
        }
        
        EventListener listener;
        listener.mName = name;
        listener.mPhase = phase;
        listener.mCallback = callback;
        // We want to allow the firstmost future event to fire without
        // allowing any past events to fire. To do this extrapolate from
        // mReferenceTime the most recent hardware vsync, and pin the
        // last event time there.
        const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        if (mPeriod != 0) {
            const nsecs_t baseTime = now - mReferenceTime;
            const nsecs_t numPeriodsSinceReference = baseTime / mPeriod;
            const nsecs_t predictedReference = mReferenceTime + numPeriodsSinceReference * mPeriod;
            const nsecs_t phaseCorrection = mPhase + listener.mPhase;
            const nsecs_t predictedLastEventTime = predictedReference + phaseCorrection;
            if (predictedLastEventTime >= now) {
                // Make sure that the last event time does not exceed the current time.
                // If it would, then back the last event time by a period.
                listener.mLastEventTime = predictedLastEventTime - mPeriod;
            } else {
                listener.mLastEventTime = predictedLastEventTime;
            }
        } else {
            listener.mLastEventTime = now + mPhase - mWakeupLatency;
        }
        
        if (lastCallbackTime <= 0) {
            // If there is no prior callback time, try to infer one based on the
            // logical last event time.
            listener.mLastCallbackTime = listener.mLastEventTime + mWakeupLatency;
        } else {
            listener.mLastCallbackTime = lastCallbackTime;
        }

        mEventListeners.push_back(listener);
        //signal 通知
        mCond.signal();
        return NO_ERROR;
    }

    virtual bool threadLoop() {
        status_t err;
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        while (true) {
            std::vector callbackInvocations;
            nsecs_t targetTime = 0;
            { // Scope for lock
                Mutex::Autolock lock(mMutex);
                if (mTraceDetailedInfo) {
                    ATRACE_INT64("DispSync:Frame", mFrameNumber);
                }
                ALOGV("[%s] Frame %" PRId64, mName, mFrameNumber);
                ++mFrameNumber;
                if (mStop) {
                    return false;
                }

                if (mPeriod == 0) {
                    //wait 等待
                    err = mCond.wait(mMutex);

                    if (err != NO_ERROR) {
                        ALOGE("error waiting for new events: %s (%d)", strerror(-err), err);
                        return false;
                    }
                    continue;
                }

                targetTime = computeNextEventTimeLocked(now);
                bool isWakeup = false;
                
                if (now < targetTime) {
                    if (mTraceDetailedInfo) ATRACE_NAME("DispSync waiting");
                    if (targetTime == INT64_MAX) {
                        ALOGV("[%s] Waiting forever", mName);
                        //wait 等待
                        err = mCond.wait(mMutex);
                    } else {
                        ALOGV("[%s] Waiting until %" PRId64, mName, ns2us(targetTime));
                        err = mCond.waitRelative(mMutex, targetTime - now);
                    }

                    if (err == TIMED_OUT) {
                        isWakeup = true;
                    } else if (err != NO_ERROR) {
                        ALOGE("error waiting for next event: %s (%d)", strerror(-err), err);
                        return false;
                    }
                }

                now = systemTime(SYSTEM_TIME_MONOTONIC);

                // Don't correct by more than 1.5 ms
                static const nsecs_t kMaxWakeupLatency = us2ns(1500);

                if (isWakeup) {
                    mWakeupLatency = ((mWakeupLatency * 63) + (now - targetTime)) / 64;
                    mWakeupLatency = min(mWakeupLatency, kMaxWakeupLatency);
                    if (mTraceDetailedInfo) {
                        ATRACE_INT64("DispSync:WakeupLat", now - targetTime);
                        ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency);
                    }
                }

                //从mEventListeners获取满足相应条件的回调,加入到集合callbackInvocations中
                callbackInvocations = gatherCallbackInvocationsLocked(now);
            }

            if (callbackInvocations.size() > 0) {
                //执行callback回调
                fireCallbackInvocations(callbackInvocations);
            }
        }
        return false;
    }

    void fireCallbackInvocations(const std::vector& callbacks) {
        if (mTraceDetailedInfo) ATRACE_CALL();
        for (size_t i = 0; i < callbacks.size(); i++) {
            callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
        }
    }


    std::vector gatherCallbackInvocationsLocked(nsecs_t now) {
        if (mTraceDetailedInfo) ATRACE_CALL();
        ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName, ns2us(now));
        std::vector callbackInvocations;
        nsecs_t onePeriodAgo = now - mPeriod;
        for (auto& eventListener : mEventListeners) {
            nsecs_t t = computeListenerNextEventTimeLocked(eventListener, onePeriodAgo);
            if (t < now) {
                if (isCloseToPeriod(now - eventListener.mLastCallbackTime)) {
                    eventListener.mLastEventTime = t;
                    ALOGV("[%s] [%s] Skipping event due to model error", mName,
                          eventListener.mName);
                    continue;
                }

                if (eventListener.mHasFired && !mModelLocked) {
                    eventListener.mLastEventTime = t;
                    ALOGV("[%s] [%s] Skipping event due to already firing", mName,
                          eventListener.mName);
                    continue;
                }

                CallbackInvocation ci;
                ci.mCallback = eventListener.mCallback;
                ci.mEventTime = t;
                ALOGV("[%s] [%s] Preparing to fire, latency: %" PRId64, mName, eventListener.mName,
                      t - eventListener.mLastEventTime);
                callbackInvocations.push_back(ci);
                eventListener.mLastEventTime = t;
                eventListener.mLastCallbackTime = now;
                eventListener.mHasFired = true;
            }
        }
        return callbackInvocations;
    }

EventThread本身继承自Thread,通过Condition唤醒当前的线程。 

1. DispSync.DispSyncThread
    void fireCallbackInvocations(const std::vector& callbacks) {
        if (mTraceDetailedInfo) ATRACE_CALL();
        for (size_t i = 0; i < callbacks.size(); i++) {
            callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
        }
    }

    struct CallbackInvocation {
        DispSync::Callback* mCallback;
        nsecs_t mEventTime;
    };

2. DispSyncSource.h
class DispSyncSource final : public VSyncSource, private DispSync::Callback

3. DispSyncSource.cpp
void DispSyncSource::onDispSyncEvent(nsecs_t when) {
    VSyncSource::Callback* callback;
    {
        std::lock_guard lock(mCallbackMutex);
        callback = mCallback;
        if (mTraceVsync) {
            mValue = (mValue + 1) % 2;
            ATRACE_INT(mVsyncEventLabel.c_str(), mValue);
        }
    }
    if (callback != nullptr) {
        callback->onVSyncEvent(when);
    }
}

4. EventThread.h
class EventThread : public android::EventThread, private VSyncSource::Callback

5. EventThread.cpp
void EventThread::onVSyncEvent(nsecs_t timestamp) {
    std::lock_guard lock(mMutex);
    LOG_FATAL_IF(!mVSyncState);
    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count));
    mCondition.notify_all();
}

最终调用到BitTube的write方法,往mSendFd描述符send对应内容。

1. EventThread.cpp
void EventThread::threadMain(std::unique_lock& lock) {
    DisplayEventConsumers consumers;
    while (mState != State::Quit) {
        std::optional event;
        // Determine next event to dispatch.
        if (!mPendingEvents.empty()) {
            event = mPendingEvents.front();
            mPendingEvents.pop_front();
            switch (event->header.type) {
                case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                    if (event->hotplug.connected && !mVSyncState) {
                        mVSyncState.emplace(event->header.displayId);
                    } else if (!event->hotplug.connected && mVSyncState &&
                              mVSyncState->displayId == event->header.displayId) {
                        mVSyncState.reset();
                    }
                    break;
                case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
                    if (mInterceptVSyncsCallback) {
                        mInterceptVSyncsCallback(event->header.timestamp);
                    }
                    break;
            }
        }

        bool vsyncRequested = false;
        // Find connections that should consume this event.
        auto it = mDisplayEventConnections.begin();
        while (it != mDisplayEventConnections.end()) {
            if (const auto connection = it->promote()) {
                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
                if (event && shouldConsumeEvent(*event, connection)) {
                    consumers.push_back(connection);
                }
                ++it;
            } else {
                it = mDisplayEventConnections.erase(it);
            }
        }

        if (!consumers.empty()) {
            dispatchEvent(*event, consumers);
            consumers.clear();
        }

        State nextState;
        if (mVSyncState && vsyncRequested) {
            nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
        } else {
            ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
            nextState = State::Idle;
        }

        if (mState != nextState) {
            if (mState == State::VSync) {
                mVSyncSource->setVSyncEnabled(false);
            } else if (nextState == State::VSync) {
                mVSyncSource->setVSyncEnabled(true);
            }
            mState = nextState;
        }
        
        if (event) {
            continue;
        }
        // Wait for event or client registration/request.
        if (mState == State::Idle) {
            mCondition.wait(lock);
        } else {
            // Generate a fake VSYNC after a long timeout in case the driver stalls. When the
            // display is off, keep feeding clients at 60 Hz.
            const auto timeout = mState == State::SyntheticVSync ? 16ms : 1000ms;
            if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
                ALOGW_IF(mState == State::VSync, "Faking VSYNC due to driver stall");
                LOG_FATAL_IF(!mVSyncState);
                mPendingEvents.push_back(makeVSync(mVSyncState->displayId,
                                                  systemTime(SYSTEM_TIME_MONOTONIC),
                                                  ++mVSyncState->count));
            }
        }
    }
}

void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
                                const DisplayEventConsumers& consumers) {
    for (const auto& consumer : consumers) {
        switch (consumer->postEvent(event)) {
            case NO_ERROR:
                break;
            case -EAGAIN:
                ...
                break;
            default:
                // Treat EPIPE and other errors as fatal.
                removeDisplayEventConnectionLocked(consumer);
        }
    }
}

status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
    ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
    return size < 0 ? status_t(size) : status_t(NO_ERROR);
}

2. EventThread.h
using DisplayEventConsumers = std::vector>
class EventThreadConnection : public BnDisplayEventConnection {
public:
    EventThreadConnection(EventThread*, ResyncCallback);
    virtual ~EventThreadConnection();
    virtual status_t postEvent(const DisplayEventReceiver::Event& event);
    status_t stealReceiveChannel(gui::BitTube* outChannel) override;
    status_t setVsyncRate(uint32_t rate) override;
    void requestNextVsync() override; // asynchronous
    // Called in response to requestNextVsync.
    const ResyncCallback resyncCallback;
    VSyncRequest vsyncRequest = VSyncRequest::None;
    
private:
    virtual void onFirstRef();
    EventThread* const mEventThread;
    gui::BitTube mChannel;
};

3. DisplayEventReceiver.cpp
ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
        Event const* events, size_t count)
{
    return gui::BitTube::sendObjects(dataChannel, events, count);
}

4. BitTube.cpp
ssize_t BitTube::sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize) {
    const char* vaddr = reinterpret_cast(events);
    ssize_t size = tube->write(vaddr, count * objSize);
    // should never happen because of SOCK_SEQPACKET
    LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast(objSize)),
                        "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were "
                        "sent!)",
                        count, objSize, size);
    // ALOGE_IF(size<0, "error %d sending %d events", size, count);
    return size < 0 ? size : size / static_cast(objSize);
}

ssize_t BitTube::write(void const* vaddr, size_t size) {
    ssize_t err, len;
    do {
        len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
        // cannot return less than size, since we're using SOCK_SEQPACKET
        err = len < 0 ? errno : 0;
    } while (err == EINTR);
    return err == 0 ? len : -err;
}

二、VSYNC的接收

在SurfaceFlinger中,首次创建实例的时候会调用到onFirstRef方法:

1. SurfaceFlinger.cpp
void SurfaceFlinger::onFirstRef()
{
    mEventQueue->init(this);
}

2. SurfaceFlinger.h
// these are thread safe
    std::unique_ptr mEventQueue;
    
3. MessageQueue.cpp
void MessageQueue::init(const sp& flinger) {
    mFlinger = flinger;
    mLooper = new Looper(true);
    mHandler = new Handler(*this);
}

上面我们已经提到了,在SurfaceFlinger的init方法中,mSfConnectionHandle对应着SurfaceFlinger自身的VSYNC的处理,是因为调用了mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle))方法。
 

1. MessageQueue.cpp
void MessageQueue::setEventConnection(const sp& connection) {
    if (mEventTube.getFd() >= 0) {
        mLooper->removeFd(mEventTube.getFd());
    }
    mEvents = connection;
    mEvents->stealReceiveChannel(&mEventTube);
    mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
                  this);
}

2. MessageQueue.h
gui::BitTube mEventTube;

3. BitTube.cpp
void BitTube::init(size_t rcvbuf, size_t sndbuf) {
    //BitTube通过SocketPair创建了两个Socket描述符
    int sockets[2];
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
        size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
        setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
        setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
        // since we don't use the "return channel", we keep it small...
        setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
        setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
        fcntl(sockets[0], F_SETFL, O_NONBLOCK);
        fcntl(sockets[1], F_SETFL, O_NONBLOCK);
        mReceiveFd.reset(sockets[0]);
        mSendFd.reset(sockets[1]);
    } else {
        mReceiveFd.reset();
        ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
    }
}

int BitTube::getFd() const {
    return mReceiveFd;
}

getFd方法返回的是mReceiveFd,MessageQueue通过Looper的addFD方法将该描述符添加到Looper中,当上述的VSYNC时间分发时,当通过send方法往mSendFd写数据时,会触发Looper中的epoll机制,从而回调到MessageQueue::cb_eventReceiver方法。MessageQueue的cb_eventReceiver方法,最终通过Looper的SendMessage调用到SurfaceFlinger的onMessageReceived方法,Message类型为MessageQueue::REFRESH:

1. SurfaceFlinger.cpp
void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS {
    ATRACE_CALL();
    switch (what) {
        case MessageQueue::INVALIDATE: {
            ...
        case MessageQueue::REFRESH: {
            if (mDolphinFuncsEnabled) {
                mDolphinRefresh();
            }
            handleMessageRefresh();
            break;
        }
    }
}

最终通过SurfaceFlinger的handleMessageRefresh方法,将App填充的最新的Layer实现计算大小,合成到framebuffer中供显卡显示。
 

三、Choreographer

从创建FrameDisplayEventReceiver开始分析,调用到它的父类DisplayEventReceiver.java的构造方法。
 

1. DisplayEventReceiver.java
    /**
    * Creates a display event receiver.
    *
    * @param looper The looper to use when invoking callbacks.
    * @param vsyncSource The source of the vsync tick. Must be on of the VSYNC_SOURCE_* values.
    */
    public DisplayEventReceiver(Looper looper, int vsyncSource) {
        if (looper == null) {
            throw new IllegalArgumentException("looper must not be null");
        }
        mMessageQueue = looper.getQueue();
        mReceiverPtr = nativeInit(new WeakReference(this), mMessageQueue,
                vsyncSource);
        mCloseGuard.open("dispose");
    }

然后通过nativeInit的jni调用android_view_DisplayEventReceiver.cpp中的nativeInit方法,通过创建NativeDisplayEventReceiver调用到它的父类DisplayEventDispatcher,通过nativeInit中传递过来的MessageQueue,得到App主线程的Looper,并交给DisplayEventDispatcher,继而调用DisplayEventDispatcher的initialize方法。
 

1. android_view_DisplayEventReceiver.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
        jobject messageQueueObj, jint vsyncSource) {
    sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    sp receiver = new NativeDisplayEventReceiver(env,
            receiverWeak, messageQueue, vsyncSource);
    status_t status = receiver->initialize();
    if (status) {
        String8 message;
        message.appendFormat("Failed to initialize display event receiver.  status=%d", status);
        jniThrowRuntimeException(env, message.string());
        return 0;
    }

    receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
    return reinterpret_cast(receiver.get());
}

class NativeDisplayEventReceiver : public DisplayEventDispatcher

2. DisplayEventDispatcher.cpp
status_t DisplayEventDispatcher::initialize() {
    status_t result = mReceiver.initCheck();
    if (result) {
        ALOGW("Failed to initialize display event receiver, status=%d", result);
        return result;
    }

    int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
            this, NULL);
    if (rc < 0) {
        return UNKNOWN_ERROR;
    }
    return OK;
}

可以看到它也是通过addFd监听着VSYNC信号的到来。而mReceiver则对应着DisplayEventReceiver则可以理解成跨进程的远程对象的本地代理。DisplayEventReceiver首先通过ComposerService创建了SurfaceFlinger的本地代理,然后通过createDisplayEventConnection得到EventThread所持有的Connection,这个Connection持有的BitTube订阅的方式和上面SurfaceFlinger一样。

1. DisplayEventReceiver.cp
DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
    sp sf(ComposerService::getComposerService());
    if (sf != nullptr) {
        mEventConnection = sf->createDisplayEventConnection(vsyncSource);
        if (mEventConnection != nullptr) {
            mDataChannel = std::make_unique();
            mEventConnection->stealReceiveChannel(mDataChannel.get());
        }
    }
}

int DisplayEventReceiver::getFd() const {
    if (mDataChannel == nullptr)
        return NO_INIT;
    return mDataChannel->getFd();
}

2. SurfaceFlinger.cpp
sp SurfaceFlinger::createDisplayEventConnection(
        ISurfaceComposer::VsyncSource vsyncSource) {
    auto resyncCallback = mScheduler->makeResyncCallback([this] {
        Mutex::Autolock lock(mStateLock);
        return getVsyncPeriod();
    });

    const auto& handle =
            vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
    return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback));
}

这里分析使用的是mSfConnectionHandle还是mAppConnectionHandle?

变量eVsyncSourceSurfaceFlinger的来历

1. ISurfaceComposer.h
    enum VsyncSource {
        eVsyncSourceApp = 0,
        eVsyncSourceSurfaceFlinger = 1
    };

反向追踪vsyncSource可知,其初始来源于Choreographer中,如下所示:

public final class Choreographer {
    ...
    private final class FrameDisplayEventReceiver extends DisplayEventReceiver
            implements Runnable {
        ...
        public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
            super(looper, vsyncSource);
        }
    }
    ...

    private Choreographer(Looper looper, int vsyncSource) {
        ...
        mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper, vsyncSource) : null;
        ...
    }
    ...

    /**
    * Gets the choreographer for the calling thread.  Must be called from
    * a thread that already has a {@link android.os.Looper} associated with it.
    *
    * @return The choreographer for this thread.
    * @throws IllegalStateException if the thread does not have a looper.
    */

    public static Choreographer getInstance() {
        return sThreadInstance.get();
    }
    /**
    * @hide
    */
    @UnsupportedAppUsage
    public static Choreographer getSfInstance() {
        return sSfThreadInstance.get();
    }
    ...

    // Thread local storage for the choreographer.
    private static final ThreadLocal sThreadInstance =
            new ThreadLocal() {
        @Override
        protected Choreographer initialValue() {
            Looper looper = Looper.myLooper();
            if (looper == null) {
                throw new IllegalStateException("The current thread must have a looper!");
            }
            Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);
            if (looper == Looper.getMainLooper()) {
                mMainInstance = choreographer;
            }
            return choreographer;
        }
    };
    
    ...
    // Thread local storage for the SF choreographer.
    private static final ThreadLocal sSfThreadInstance =
            new ThreadLocal() {
                @Override
                protected Choreographer initialValue() {
                    Looper looper = Looper.myLooper();
                    if (looper == null) {
                        throw new IllegalStateException("The current thread must have a looper!");
                    }
                    return new Choreographer(looper, VSYNC_SOURCE_SURFACE_FLINGER);
                }
            };
    ...
}

public abstract class DisplayEventReceiver {
    /**
    * When retrieving vsync events, this specifies that the vsync event should happen at the normal
    * vsync-app tick.
    * 

* Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h */ public static final int VSYNC_SOURCE_APP = 0; /** * When retrieving vsync events, this specifies that the vsync event should happen whenever * Surface Flinger is processing a frame. *

* Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h */ public static final int VSYNC_SOURCE_SURFACE_FLINGER = 1; ... }

在ViewRootImpl中初始化Choreographer使用的是Choreographer.getInstance()即可知,最终生成的mAppConnectionHandle。所以Choreographer通过mAppConnectionHandle所对应的EventThread建立的连接而不是mSfConnectionHandle。就这样Choreographer成功的订阅了VSYNC信号。
 

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
    ...
    public ViewRootImpl(Context context, Display display) {
    ...
    mChoreographer = Choreographer.getInstance();
    ...
    }
    ...
}

而当Vsync信号到来的时候,由于DisplayEventDispatcher继承了LooperCallback,会调用到它的handleEvent方法,继而调用到NativeDisplayEventReceiver的dispatchVsync方法:
 

1. android_view_DisplayEventReceiver.cpp
class NativeDisplayEventReceiver : public DisplayEventDispatcher

2. DisplayEventDispatcher.h
class DisplayEventDispatcher : public LooperCallback

3. DisplayEventDispatcher.cpp
int DisplayEventDispatcher::handleEvent(int, int events, void*) {
    ...
    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
        ...
        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
    }
    return 1; // keep the callback
}

4. android_view_DisplayEventReceiver.cpp
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId,
                                              uint32_t count) {
    JNIEnv* env = AndroidRuntime::getJNIEnv();
    ScopedLocalRef receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
    if (receiverObj.get()) {
        ...
        env->CallVoidMethod(receiverObj.get(),
                gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, displayId, count);
        ...
    }
    mMessageQueue->raiseAndClearException(env, "dispatchVsync");
}

int register_android_view_DisplayEventReceiver(JNIEnv* env) {
    int res = RegisterMethodsOrDie(env, "android/view/DisplayEventReceiver", gMethods,
                                  NELEM(gMethods));
    jclass clazz = FindClassOrDie(env, "android/view/DisplayEventReceiver");
    gDisplayEventReceiverClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
    gDisplayEventReceiverClassInfo.dispatchVsync = GetMethodIDOrDie(env,
            gDisplayEventReceiverClassInfo.clazz, "dispatchVsync", "(JJI)V");
    gDisplayEventReceiverClassInfo.dispatchHotplug = GetMethodIDOrDie(env,
            gDisplayEventReceiverClassInfo.clazz, "dispatchHotplug", "(JJZ)V");
    gDisplayEventReceiverClassInfo.dispatchConfigChanged = GetMethodIDOrDie(env,
          gDisplayEventReceiverClassInfo.clazz, "dispatchConfigChanged", "(JJI)V");
    return res;
}

5. DisplayEventReceiver.java
    // Called from native code.
    @SuppressWarnings("unused")
    @UnsupportedAppUsage
    private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame) {
        onVsync(timestampNanos, physicalDisplayId, frame);
    }

jni端会通过CallVoidMethod方法调用到java端的DisplayEventReceiver的dispatchVsync方法,继而调用到FrameDisplayEventReceiver的onVsync方法。

你可能感兴趣的:(android P Choreographer与SurfaceFlinger)