Android graphics(三) surfaceflinger

一、前言

本文主要内容
1、surfaceflinger初始化流程;
2、surfaceflinger消息机制;
3、surfaceflinger绘制流程;
4、VSync分发流程

surfaceFlinger由init进程启动,独立进程运行,它接受来自多个来源的数据缓冲区,对它们进行合成,然后发送到显示设备。
简述显示过程
1>、一个页面,一般分为三个window,状态栏、app和导航栏,每个window看作要显示的一层,windowManager显示时,请求surfaceflinger为每个window创建衣蛾surface(layer)来绘制显示
每一个显示layer层,我们看作一个bufferqueue缓存队列。surfaceflinger合成bufferqueue,合成后送到Hardware Composer显示。
2>、显示按照一定刷新率更新画面,手机平板通常为60fps(16.6ms显示一次),一次刷新由vsync信号发起,surfaceflinger接收到信号后组织这一次刷新显示。
3>、当 VSYNC 信号到达时,SurfaceFlinger 会遍历它的层列表,以寻找新的缓冲区。如果找到新的缓冲区,它会获取该缓冲区;
否则,它会继续使用以前获取的缓冲区。SurfaceFlinger 必须始终显示内容,因此它会保留一个缓冲区。如果在某个层上没有提交缓冲区,则该层会被忽略。
备注:本文只列出关键代码,关键流程。

二、surfaceflinger启动流程

2.1、main入口

surfaceflinger.rc由init.rc启动,main_surfaceflinger.cpp main函数为启动入口   

int main(int, char**) {
    startGraphicsAllocatorService();
    // instantiate surfaceflinger
    sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
    // initialize before clients can connect
    flinger->init();


    // publish surface flinger
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
                   IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);


    flinger->run();
}

提炼其中重要三件事情,主要还是一个surfaceFlinger的创建
1、createSurfaceFlinger并init(伴随onFirstRef)
2、addService到上层
3、进入消息循环

2.2、surfaceflinger构造

class SurfaceFlinger : public BnSurfaceComposer,
                       public PriorityDumper,
                       private IBinder::DeathRecipient,
                       private HWC2::ComposerCallback,
                       private ISchedulerCallback {

SurfaceComposer继承自BnSurfaceComposer,即为实现了ISurfaceComposer接口的Bn服务端;
Dump信息PriorityDumper;
死亡通知DeathRecipient,当Binder服务端程序挂掉后,可以通知给绑定的Binder客户端程序;
实现了HWC2的ComposerCallback回调,监听Composer HAL的一些事件,比如Hotplug, Vsync ...

2.3、消息队列SurfaceFlinger::onFirstRef

这里引出surfaceflinger重点之一surfaceflinger的消息队列。后面单独讲
SurfaceFlinger继承RefBase类,所以此处一旦new出对象赋给sp指针后,将立刻触发SurfaceFlinger类的onFirstRef方法的调用。

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

2.4、SurfaceFlinger::init

// Do not call property_set on main thread which will be blocked by init
// Use StartPropertySetThread instead.
void SurfaceFlinger::init() {
    // Get a RenderEngine
    mCompositionEngine->setRenderEngine(renderengine::RenderEngine::create(
            renderengine::RenderEngineCreationArgs::Builder()
                    .setPixelFormat(static_cast<int32_t>(defaultCompositionPixelFormat))
                    .setImageCacheSize(maxFrameBufferAcquiredBuffers)
                    .setUseColorManagerment(useColorManagement)
                    .setEnableProtectedContext(enable_protected_contents(false))
                    .setPrecacheToneMapperShaderOnly(false)
                    .setSupportsBackgroundBlur(mSupportsBlur)
                    .setContextPriority(
                            useContextPriority
                                    ? renderengine::RenderEngine::ContextPriority::REALTIME
                                    : renderengine::RenderEngine::ContextPriority::MEDIUM)
                    .build()));


    // 创建HWComposer,通过mCompositionEngine->setHwComposer设置对象属性,并注册回调
    mCompositionEngine->setTimeStats(mTimeStats);
    mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
    mCompositionEngine->getHwComposer().setCallback(this);
    ClientCache::getInstance().setRenderEngine(&getRenderEngine());


    // 任何初始热插拔和显示更改的结果
    processDisplayHotplugEventsLocked();
    const auto display = getDefaultDisplayDeviceLocked();
    LOG_ALWAYS_FATAL_IF(!display, "Missing internal display after registering composer callback.");
    const auto displayId = display->getPhysicalId();
    LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(displayId),
                        "Internal display is disconnected.");


    // 初始化display
    initializeDisplays();


    // 开启一个设置属性的线程
    if (mStartPropertySetThread->Start() != NO_ERROR) {
        ALOGE("Run StartPropertySetThread failed!");
    }
}

init方法主要做了这么几件事情:
1、创建一个RenderEngine
2、创建HWComposer,通过mCompositionEngine->setHwComposer设置对象属性,并注册回调
3、处理Display显示屏幕的热插拔
4、初始化显示设备
5、开启设置属性线程

2.5、SurfaceFlinger::run

main函数中最后一步,run开启无限循环等待消息

void SurfaceFlinger::run() {
    while (true) {
        mEventQueue->waitMessage();
    }
}

2.5小结

上面五个小点总结了surfaceflinger的初始化过程。整体来说初始化更多还是对象的创建,要更加深入的理解surfaceflinger,
我们还应该剖析一些重要流程出来理解。这样才有助于理解surfaceflinger在绘制过程中如何承上启下

三、Surfaceflinger消息队列

在surafceflinger的构造函数中初始化

SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
      : ...
        mEventQueue(mFactory.createMessageQueue()),
        
//framework/native/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
/frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.h     
//frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
std::unique_ptr<MessageQueue> DefaultFactory::createMessageQueue() {
    return std::make_unique<android::impl::MessageQueue>();
}


//framework/native/services/surfaceflinger/Scheduler/MessageQueue.h
class MessageQueue {
public:
    enum {
        INVALIDATE = 0,
        REFRESH = 1,
    };


    virtual ~MessageQueue() = default;


    virtual void init(const sp<SurfaceFlinger>& flinger) = 0;
    virtual void initVsync(scheduler::VSyncDispatch&, frametimeline::TokenManager&,
                           std::chrono::nanoseconds workDuration) = 0;
    virtual void setDuration(std::chrono::nanoseconds workDuration) = 0;
    virtual void setInjector(sp<EventThreadConnection>) = 0;
    virtual void waitMessage() = 0;
    virtual void postMessage(sp<MessageHandler>&&) = 0;
    virtual void invalidate() = 0;
    virtual void refresh() = 0;
    virtual std::optional<std::chrono::steady_clock::time_point> nextExpectedInvalidate() = 0;
};

如上代码,surfaceflinger消息队列中,重要的两个事件,INVALIDATEREFRESH

// framework/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
void MessageQueue::Handler::dispatchRefresh() {
    if ((mEventMask.fetch_or(eventMaskRefresh) & eventMaskRefresh) == 0) {
        mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
    }
}


void MessageQueue::Handler::dispatchInvalidate(int64_t vsyncId, nsecs_t expectedVSyncTimestamp) {
    if ((mEventMask.fetch_or(eventMaskInvalidate) & eventMaskInvalidate) == 0) {
        mVsyncId = vsyncId;
        mExpectedVSyncTime = expectedVSyncTimestamp;
        mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
    }
}


void MessageQueue::Handler::handleMessage(const Message& message) {
    switch (message.what) {
        case INVALIDATE:
            mEventMask.fetch_and(~eventMaskInvalidate);
            mQueue.mFlinger->onMessageReceived(message.what, mVsyncId, mExpectedVSyncTime);
            break;
        case REFRESH:
            mEventMask.fetch_and(~eventMaskRefresh);
            mQueue.mFlinger->onMessageReceived(message.what, mVsyncId, mExpectedVSyncTime);
            break;
    }
}

消息队列又处理回surfaceflinger中的onMessageReceived方法

//SurfaceFlinger.cpp
void SurfaceFlinger::onMessageReceived(int32_t what, nsecs_t expectedVSyncTime) {
    ATRACE_CALL();
    switch (what) {
        case MessageQueue::INVALIDATE: {
            onMessageInvalidate(expectedVSyncTime);
            break;
        }
        case MessageQueue::REFRESH: {
            onMessageRefresh();
            break;
        }
    }
}

这里摘录一个bufferqueue的acquireBuffer方法时的堆栈
vsync刷新信号过来onMessageReceived收到消息后,bufferqueue开始处理图像队列

04-19 19:33:38.926   666   666 E acquireBuffer: #00 pc 0004d34f  /system/lib/libgui.so (android::BufferQueueConsumer::acquireBuffer(android::BufferItem*, long long, unsigned long long)+74)
04-19 19:33:38.926   666   666 E acquireBuffer: #01 pc 000645cf  /system/lib/libgui.so (android::ConsumerBase::acquireBufferLocked(android::BufferItem*, long long, unsigned long long)+62)
04-19 19:33:38.926   666   666 E acquireBuffer: #02 pc 0007a7a1  /system/lib/libsurfaceflinger.so (android::FramebufferSurface::advanceFrame(bool)+112)
04-19 19:33:38.926   666   666 E acquireBuffer: #03 pc 000edf1f  /system/lib/libsurfaceflinger.so (android::compositionengine::impl::RenderSurface::queueBuffer(android::base::unique_fd_impl<android::base::DefaultCloser>, bool)+358)
04-19 19:33:38.926   666   666 E acquireBuffer: #04 pc 000e46e7  /system/lib/libsurfaceflinger.so (android::compositionengine::impl::Output::finishFrame(android::compositionengine::CompositionRefreshArgs const&)+454)
04-19 19:33:38.926   666   666 E acquireBuffer: #05 pc 000de3e5  /system/lib/libsurfaceflinger.so (android::compositionengine::impl::Display::finishFrame(android::compositionengine::CompositionRefreshArgs const&)+72)
04-19 19:33:38.926   666   666 E acquireBuffer: #06 pc 000e3011  /system/lib/libsurfaceflinger.so (android::compositionengine::impl::Output::present(android::compositionengine::CompositionRefreshArgs const&)+92)
04-19 19:33:38.926   666   666 E acquireBuffer: #07 pc 000dcfa1  /system/lib/libsurfaceflinger.so (android::compositionengine::impl::CompositionEngine::present(android::compositionengine::CompositionRefreshArgs&)+144)
04-19 19:33:38.926   666   666 E acquireBuffer: #08 pc 000baf81  /system/lib/libsurfaceflinger.so (android::SurfaceFlinger::onMessageRefresh()+1280)
04-19 19:33:38.926   666   666 E acquireBuffer: #09 pc 000b8b1d  /system/lib/libsurfaceflinger.so (android::SurfaceFlinger::onMessageReceived(int, long long)+52)

四、surfaceflinger绘制流程

4.1、wms和surfaceflinger创建surface流程

4.1.1、wms和surfaceflinger建立连接

要显示的页面通过window告诉surfaceflinger创建surface来绘图,这个surface就是一个layer(layer的核心就是buffer queue);
surfaceflinger创建的bufferqueue不会传递到app,而是通过内存共享直接供app绘制。bufferqueue都不会传递;
那么这一节内容我们来讲讲这个流程

//WMS
public int addWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) {
    win.attach(); // WindowState
}


// WindowState.attch
void attach() {
    mSession.windowAddedLocked();
}


void windowAddedLocked(String packageName) {
    if (mSurfaceSession == null) {
        mSurfaceSession = new SurfaceSession();
    }
}


// SurfaceSession.java
private long mNativeClient; // SurfaceComposerClient*


/** Create a new connection with the surface flinger. */
public SurfaceSession() {
    mNativeClient = nativeCreate();
}


// frameworks/base/core/jni/android_view_SurfaceSession.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    SurfaceComposerClient* client = new SurfaceComposerClient();
    client->incStrong((void*)nativeCreate);
    return reinterpret_cast<jlong>(client);
}


void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposerClient> conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) : sf->createConnection();
    if (conn != 0) {
        mClient = conn;
    }
    // ...
}


sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
    return initClient(new Client(this)); // initClient方法只是调用initCheck检查了一下
}

上面截取了一段流程代码:
1>、从我们熟知的addwindow开始,WindowSate表示一个window;
2>、mSurfaceSession表示一个跟surfaceflinger的连接,其中SurfaceComposerClient就是表示连接的指针;
3>、最后创建的Client实现ISurfaceComposerClient的aidl,它可以创建Surface,并且维护一个应用程序的所有Layer;

4.1.2、Surface创建对应Layer

// ViewRootImpl.java
public final Surface mSurface = new Surface();
一个ViewRootImpl对应一个Surface(上层surface),而Surface 在 SurfaceFlinger 中对应的实体是 Layer 对象。  
1>、一个Vsync信号(vysnc发起页面刷新流程)执行ViewRootImpl.performTraversals    

private void performTraversals() {
    relayoutWindow(params, viewVisibility, insetsPending)
    // measure, layout, draw
}


private int relayoutWindow(...) throws RemoteException {
    // 最后一个参数 mSurface 就是之前创建的 Surface 对象
    mWindowSession.relayout(mWindow, ..., mSurface);
}


// WMS
public int relayoutWindow(Session session, ..., Surface outSurface) {
    result = createSurfaceControl(outSurface, result, win, winAnimator);
}


private int createSurfaceControl(Surface outSurface, int result, WindowState win, WindowStateAnimator winAnimator) {
    WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
    if (surfaceController != null) {
        surfaceController.getSurface(outSurface);
    } else {
        outSurface.release();
    }
    return result;
}

上面这一段主要是为了说明relayoutWindow会createSurfaceControl
2>、surface的layer创建由SurfaceControl来进行

private SurfaceControl(...) {
    // 返回 native SurfaceControl 指针
    mNativeObject = nativeCreate(session, name, w, h, format, flags, parent != null ? parent.mNativeObject : 0, windowType, ownerUid);
}


// frameworks/base/core/jni/android_view_SurfaceControl.cpp
static jlong nativeCreate(...) {
    // client 即wms和surfaceflinger建立连接时的SurfaceComposerClient指针  
    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
    client->createSurfaceChecked(String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid);
}


// framework/native/libs/gui/SurfaceComposerClient.cpp
status_t SurfaceComposerClient::createSurfaceChecked(..., sp<SurfaceControl>* outSurface, ...) {
    err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),
                                     &handle, &gbp, &id, &transformHint);
}


//framework/native/services/surfaceflinger/Client.cpp
status_t Client::createSurface(...) {
    return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
                                 parentHandle, outLayerId, nullptr, outTransformHint);
}

这里来来回回最后还是SurfaceComposerClient指针组织了createSurface,即创建了surface对应的layer

4.1.3、上层surface和Layer对应起来

createSurfaceControl创建了layer,接着立马getSurface创建对应关系
因为上层创建的surface还是一个空的对象,copyFrom等于就是填充了surface的内容
接上面4.1.2中createSurfaceControl方法中的surfaceController.getSurface(outSurface)

// outSurface是上层ViewRootImpl创建的surface
void getSurface(Surface outSurface) {
    outSurface.copyFrom(mSurfaceControl);
}


// Surface.java
public void copyFrom(SurfaceControl other) {
    long surfaceControlPtr = other.mNativeObject;
    // mNativeObject是4.2.2 小结 SurfaceControl创建时返回的指针
    long newNativeObject = nativeGetFromSurfaceControl(surfaceControlPtr);


    synchronized (mLock) {
        if (mNativeObject != 0) {
            nativeRelease(mNativeObject);
        }
        // 把指针赋值给mNativeObject
        setNativeObjectLocked(newNativeObject);
    }
}


private void setNativeObjectLocked(long ptr) {
    if (mNativeObject != ptr) {
        mNativeObject = ptr;
        if (mHwuiContext != null) {
            mHwuiContext.updateSurface();
        }
    }
}


// frameworks/base/core/jni/android_view_Surface.cpp
static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz, jlong surfaceControlNativeObj) {
    // java指针和底层指针的转换
    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
    sp<Surface> surface(ctrl->getSurface());
    if (surface != NULL) {
        surface->incStrong(&sRefBaseOwner);
    }
    return reinterpret_cast<jlong>(surface.get());
}


sp<Surface> SurfaceControl::getSurface() const
{
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == 0) {
        return generateSurfaceLocked();
    }
    return mSurfaceData;
}


sp<Surface> SurfaceControl::generateSurfaceLocked() const
{
    // mGraphicBufferProducer 是上面创建的 gbp 对象
    // 这里new surface实际是底层的surface
    mSurfaceData = new Surface(mGraphicBufferProducer, false);
    return mSurfaceData;
}

1、nativeGetFromSurfaceControl 返回native Suface的指针,指针的值赋给SurfaceControl.mNativeObject
2、上层surface调用copyFrom填充内容时,实际就是拿到了SurfaceControl了,也拥有了底层的surface指针,子集关系。

4.2、Vysnc流程

4.2.1 几点概念

1、VSYNC 信号可同步显示流水线。显示流水线由应用渲染、SurfaceFlinger 合成以及用于在屏幕上显示图像的硬件混合渲染器 (HWC) 组成。
2、VSYNC 可同步应用唤醒以开始渲染的时间、SurfaceFlinger 唤醒以合成屏幕的时间以及屏幕刷新周期。这种同步可以消除卡顿,并提升图形的视觉表现。
3、vysnc的引入,可以及时的告知cpu/gpu暂停别的事情,及时处理显示的这一帧。从而减少卡顿发生。
4、三级缓存:vsync+三级缓存,当第n+1处理不过来的时候,由于有三次缓存数据,即使n+1卡顿,或者n+1和n+2卡顿,只要没有连着卡三次,都有缓存可以拿,UI上就不会造成卡顿。

4.2.2 DispSync

DispSync 维护屏幕基于硬件的周期性 VSYNC 事件的模型


image.png

我们一共有三个信号,HW_VYNC_0 是硬件产生的同步信号
DispSync则负责产生由Choreographer 和 SurfaceFlinger 使用的 VSYNC 和 SF_VSYNC 信号,不管是否接收到HW_VYSNC_0都会产生,HW_VYSNC_0只是起到参考作用

4.2.3 Vync的偏移

image.png

HW_VSYNC_0 - 屏幕开始显示下一帧。
VSYNC - 应用读取输入内容并生成下一帧。
SF_VSYNC - SurfaceFlinger 开始为下一帧进行合成
VSYNC_EVENT_PHASE_OFFSET_NS 和 SF_VSYNC_EVENT_PHASE_OFFSET_NS 对应phase-app和phase-sf,默认都为0

偏移量的加入是为了减少延迟,我们以正常情况来讲,一帧16.6ms就能渲染完成。App可以在phase-sf - phase-app时间内完成绘制,SurfaceFlinger可以在VSync周期 - phase-sf时间内完成合成,那么在下一个VSync信号时就可以上屏,即帧延迟为16ms。这样理想情况下,延迟就被控制成了一帧。
如果app绘制超时,sf就会在下一帧绘制,增加了一帧的周期。所以一般情况下,系统都会将phase-sf - phase-app设置为VSync周期。这样不管出现怎样的延迟现象,sf的延迟周期都是控制为一帧一帧的增加。

4.2.4 Vync代码流程

简述整个过程:
1、整个Vsync流程是从HWC监听硬件产生的Vsync开始,由DispSync维护VSYNC模型,Vsync信号是一直存在的。
2、app请求vsync
一个页面并不是无时无刻都在刷新,当触摸view发生变化,请求焦点,开始动画或者startActivity等等时,ViewRootImpl会调用scheduleTraversals流程,这个流程会让app接收下一个Vsync信号。
就是不管哪个方式刷新view都是scheduleTraversals来触发

   scheduleTraversals -> mChoreographer.postCallback() -> doScheduleVsync -> scheduleVsyncLocked -> nativeScheduleVsync -> requestNextVsync()

3、app接收vsync
收到信号后会控制view通过performTraversals方法绘制三大流程

   onVsync -> doFrame -> TraversalRunnable -> doTraversal() -> performTraversals()

4.2.4.1 Vsync初始化

分几个部分:
1、initScheduler 初始化vysnc机制
2、createVsyncSchedule:VSyncTracker、VSyncDispatch、VsyncController

initScheduler部分

//frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h
struct ComposerCallback {
    // 热插拔事件
    virtual void onComposerHalHotplug(hal::HWDisplayId, hal::Connection) = 0; 
    // refresh 刷新事件
    virtual void onComposerHalRefresh(hal::HWDisplayId) = 0; 
    // VSYNC信号事件
    virtual void onComposerHalVsync(hal::HWDisplayId, int64_t timestamp, 
                                    std::optional<hal::VsyncPeriodNanos>) = 0;
};

//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::init() {
    mCompositionEngine->setTimeStats(mTimeStats);
    mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
    // init方法注册回调开始,注册回调会立马触发onComposerHalHotplug方法
    mCompositionEngine->getHwComposer().setCallback(this); 
}

//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::onComposerHalHotplug(hal::HWDisplayId hwcDisplayId,
                                          hal::Connection connection) {
    if (std::this_thread::get_id() == mMainThreadId) {
        // Process all pending hot plug events immediately if we are on the main thread.
        processDisplayHotplugEventsLocked(); // 主线程中去处理 hot plug evnets
    }
}

//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::processDisplayHotplugEventsLocked() {
        if (event.connection == hal::Connection::CONNECTED) {
                if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
                    initScheduler(state); // 初始化Scheduler
                }
}

上面这部分代码initScheduler流程,是Vsync初始开始的地方,代码是从surfaceflinger::init开始,给HWC setCallback,直接回调hotplag热插拔,开始Scheduler的初始化
接下来就是initScheduler具体内容:

void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) {
    if (mScheduler) {
        // In practice it's not allowed to hotplug in/out the primary display once it's been
        // connected during startup, but some tests do it, so just warn and return.
        ALOGW("Can't re-init scheduler");
        return;
    }
    const auto displayId = displayState.physical->id;
    scheduler::RefreshRateConfigs::Config config =
            {.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),
             .frameRateMultipleThreshold =
                     base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)};
    // 配置信息,刷新率刷新周期Period
    mRefreshRateConfigs =
            std::make_unique<scheduler::RefreshRateConfigs>(displayState.physical->supportedModes,
                                                            displayState.physical->activeMode
                                                                    ->getId(),
                                                            config);
    const auto currRefreshRate = displayState.physical->activeMode->getFps();
    // fps信息
    mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate,
                                                                      hal::PowerMode::OFF);
    // 不同分辨率下的VSYNC配置信息
    mVsyncConfiguration = getFactory().createVsyncConfiguration(currRefreshRate);
    mVsyncModulator = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());

    // 创建Scheduler对象
    mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this);
    const auto configs = mVsyncConfiguration->getCurrentConfigs();
    const nsecs_t vsyncPeriod = currRefreshRate.getPeriodNsecs();
    //创建一个名字为app的connection
     mAppConnectionHandle =
            mScheduler->createConnection("app", mFrameTimeline->getTokenManager(),
                                         /*workDuration=*/configs.late.appWorkDuration,
                                         /*readyDuration=*/configs.late.sfWorkDuration,
                                         impl::EventThread::InterceptVSyncsCallback());
    //创建一个名字为appsf的connection                                    
    mSfConnectionHandle =
            mScheduler->createConnection("appSf", mFrameTimeline->getTokenManager(),
                                         /*workDuration=*/std::chrono::nanoseconds(vsyncPeriod),
                                         /*readyDuration=*/configs.late.sfWorkDuration,
                                         [this](nsecs_t timestamp) {
                                             mInterceptor->saveVSyncEvent(timestamp);
                                         });
    //initVsync主要作用是绑定一个回调函数 MessageQueue::vsyncCallback 到VSyncDispatch上,回调名字"sf"
    mEventQueue->initVsync(mScheduler->getVsyncDispatch(), *mFrameTimeline->getTokenManager(),
                           configs.late.sfWorkDuration);

    mRegionSamplingThread =
            new RegionSamplingThread(*this, RegionSamplingThread::EnvironmentTimingTunables());
    mFpsReporter = new FpsReporter(*mFrameTimeline, *this);
    mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, displayId,
                                            displayState.physical->activeMode->getId(),
                                            vsyncPeriod);
    static auto ignorePresentFences =
            base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false);
    mScheduler->setIgnorePresentFences(
            ignorePresentFences ||
            getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE));
}

简述流程:
1、HwComposer注册回调会立马触发onComposerHalHotplug方法,热插拔立马initScheduler
2、配置fps、刷新周期、Vsync信息、app/sf偏移量、创建Scheduler、sf/appSf/app 三个callback

createVsyncSchedule

struct VsyncSchedule {
        std::unique_ptr<scheduler::VsyncController> controller;
        std::unique_ptr<scheduler::VSyncTracker> tracker;
        std::unique_ptr<scheduler::VSyncDispatch> dispatch;
    };

Scheduler::VsyncSchedule Scheduler::createVsyncSchedule(bool supportKernelTimer) {
    auto clock = std::make_unique<scheduler::SystemClock>();
    auto tracker = createVSyncTracker();
    auto dispatch = createVSyncDispatch(*tracker);

    // TODO(b/144707443): Tune constants.
    constexpr size_t pendingFenceLimit = 20;
    auto controller =
            std::make_unique<scheduler::VSyncReactor>(std::move(clock), *tracker, pendingFenceLimit,
                                                      supportKernelTimer);
    return {std::move(controller), std::move(tracker), std::move(dispatch)};
}

创建VSyncTracker、VSyncDispatch、VsyncController封装到VsyncSchedule并返回

名称 作用
VSyncTracker 根据硬件的Vysnc、历史数据建立一个Vsync模型,预测Vsync信号
VSyncDispatch 分发Vsync回调
VsyncController 配合tracker采样
Connection app,appSf,sf三个监听vysnc

初始化部分主要介绍创建了哪些东西,vysnc运行机制的相关主角基本都列出来了。接下来我们先讲App请求Vsync和app接收Vsync。然后讲解Vsync的运作。

4.2.4.2、App请求Vsync

前面有简单提到app怎么开始请求vsync:

   scheduleTraversals -> mChoreographer.postCallback() -> doScheduleVsync -> scheduleVsyncLocked -> nativeScheduleVsync -> requestNextVsync()

本文介绍的重点是surfaceflinger,所以我们来详细看下请求这个过程,surfaceflinger做了什么,java层也比较简单,跟着上面的流程去追一下就好。

DisplayEventReceiver.java
public void scheduleVsync() {
        ...
        nativeScheduleVsync(mReceiverPtr);
    }

///android_view_DisplayEventReceiver.cpp
static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
    sp<NativeDisplayEventReceiver> receiver =
            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
    status_t status = receiver->scheduleVsync();
    ...
}

//DisplayEventDispatcher.cpp
status_t DisplayEventDispatcher::scheduleVsync() {
    ...
    status_t status = mReceiver.requestNextVsync();
    ...  
    return OK;
}

//DisplayEventReceiver.cpp
status_t DisplayEventReceiver::requestNextVsync() {
    if (mEventConnection != nullptr) {
        mEventConnection->requestNextVsync();
        return NO_ERROR;
    }
    return NO_INIT;
}

///EventThread.cpp 
void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
    if (connection->resyncCallback) {
        connection->resyncCallback();
    }

    std::lock_guard<std::mutex> lock(mMutex);

    if (connection->vsyncRequest == VSyncRequest::None) {
        connection->vsyncRequest = VSyncRequest::Single;
        mCondition.notify_all();
    } else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) {
        connection->vsyncRequest = VSyncRequest::Single;
    }
}

App请求sync的流程,主要还是一个间接调用。在mCondition.notify_all唤醒锁后,继续后边的流程

4.2.4.3、App接收Vsync

//EventThread.cpp 
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
    DisplayEventConsumers consumers;
    //1、如果队列不为空取一次vsync的event事件出来
    if (!mPendingEvents.empty()) {
            event = mPendingEvents.front();
            mPendingEvents.pop_front();
    ...
    //2、先取出一个connection ,然后用shouldConsumeEvent判断是否发送到connection
    //这里无限循环,会取出所有需要分发消息的connection
    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);
            }
        } else {
            it = mDisplayEventConnections.erase(it);
        }
    }
    ...
    //3、前面两个都满足了consumers就不为空,就开始分发
    if (!consumers.empty()) {
        dispatchEvent(*event, consumers);
        consumers.clear();
    }
    ...
    //4、上述两个条件没有满足,会走到这里wait,直到有请求来notify唤醒,也就是上面的notify_all
    if (mState == State::Idle) {
        mCondition.wait(lock);
    }

1、这样EventThread就起到了一个有请求才会vsync的监测作用。
2、注意consumers是所有需要分发dispatchEvent的connection合集
3、继续dispatchEvent流程

//EventThread.cpp
void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
                                const DisplayEventConsumers& consumers) {
    for (const auto& consumer : consumers) {
        switch (consumer->postEvent(copy)) {

status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
    constexpr auto toStatus = [](ssize_t size) {
        ...
        auto size = DisplayEventReceiver::sendEvents(&mChannel, mPendingEvents.data(),
                                                     mPendingEvents.size());
                                                     
//DisplayEventReceiver.cpp 
ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
        Event const* events, size_t count)
{
    return gui::BitTube::sendObjects(dataChannel, events, count);
}

//BitTube.cpp 
ssize_t BitTube::sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize) {
    const char* vaddr = reinterpret_cast<const char*>(events);
    ssize_t size = tube->write(vaddr, count * 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;
}

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

这里稍作解释:
1、dispatchEvent流程一层一层调用会通过BitTube来传递信息
2、BitTube用Linux/Unix中的socketpair进行跨进程数据传递,
3、成员变量mReceiveFd,看起来是一个接收端,实际上这个fd也可以用来发送,同样mSendFd也可以用来接收,只是BitTube是按照单向方式使用它的:一端写入数据,另一端读出数据
4、这里我们可以简单理解为mSendFd用来发送,mReceiveFd对端用来接收。

//DisplayEventDispatcher.cpp
status_t DisplayEventDispatcher::initialize() {
    ...
    int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL);
}

int DisplayEventDispatcher::handleEvent(int, int events, void*) {
    ...
    // Drain all pending events, keep the last vsync.
    nsecs_t vsyncTimestamp;
    PhysicalDisplayId vsyncDisplayId;
    uint32_t vsyncCount;
    VsyncEventData vsyncEventData;
    //processPendingEvents取出一个有效的sync event
    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
        mWaitingForVsync = false;
        //分发
        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
}
        
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId,
                                               uint32_t count, VsyncEventData vsyncEventData) {
    JNIEnv* env = AndroidRuntime::getJNIEnv();

    ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
    if (receiverObj.get()) {
        ALOGV("receiver %p ~ Invoking vsync handler.", this);
        // 调用到java层dispatchVsync方法
        env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync,
                            timestamp, displayId.value, count, vsyncEventData.id,
                            vsyncEventData.deadlineTimestamp, vsyncEventData.frameInterval);
        ALOGV("receiver %p ~ Returned from vsync handler.", this);
    }

    mMessageQueue->raiseAndClearException(env, "dispatchVsync");
}

//DisplayEventReceiver.java
@SuppressWarnings("unused")
private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame,
        long frameTimelineVsyncId, long frameDeadline, long frameInterval) {
    onVsync(timestampNanos, physicalDisplayId, frame,
            new VsyncEventData(frameTimelineVsyncId, frameDeadline, frameInterval));
}

public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
                VsyncEventData vsyncEventData) {
    ...
    mTimestampNanos = timestampNanos;
    mFrame = frame;
    mLastVsyncEventData = vsyncEventData;
    Message msg = Message.obtain(mHandler, this);
    msg.setAsynchronous(true);
    mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
    
 private final class FrameHandler extends Handler {
    public FrameHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_DO_FRAME:
                doFrame(System.nanoTime(), 0, new DisplayEventReceiver.VsyncEventData());
                break;
            case MSG_DO_SCHEDULE_VSYNC:
                doScheduleVsync();
                break;
            case MSG_DO_SCHEDULE_CALLBACK:
                doScheduleCallback(msg.arg1);
                break;
        }
    }
}

接收流程
1、有vysnc请求,有需要发送的connection,下一次vysnc event开始dispatchevent
2、dispatchevent间接由DisplayEventDispatcher来负责分发
3、分发时,间接调用java层dispatchVsync,由上层控制绘制view

4.2.4.4、surfaceflinger接收Vsync

1、有了上面app收发,基本就理解vsync是怎么被分发出去了。
2、在initScheduler流程时,实际我们创建了三个监听app、appSf、sf,app就是app的收发,appSf这个监听主要为surfaceflinger的工作线程服务,sf则用来通知surfaceflinger合成显示流程
3、接着surfaceflinger::initScheduler

mEventQueue->initVsync(mScheduler->getVsyncDispatch(), *mFrameTimeline->getTokenManager(),
                           configs.late.sfWorkDuration);

///MessageQueue.cpp
void MessageQueue::setInjector(sp<EventThreadConnection> connection) {
    ...
        mLooper->addFd(
                tube.getFd(), 0, Looper::EVENT_INPUT,
                [](int, int, void* data) {
                    reinterpret_cast<MessageQueue*>(data)->injectorCallback();
                    return 1; // Keep registration.
                },
                this);
    }
    
void MessageQueue::Handler::handleMessage(const Message& message) {
    switch (message.what) {
        case INVALIDATE:
            mEventMask.fetch_and(~eventMaskInvalidate);
            mQueue.mFlinger->onMessageReceived(message.what, mVsyncId, mExpectedVSyncTime);
            break;
        case REFRESH:
            mEventMask.fetch_and(~eventMaskRefresh);
            mQueue.mFlinger->onMessageReceived(message.what, mVsyncId, mExpectedVSyncTime);
            break;
    }
}

//SurfaceFlinger.cpp
void SurfaceFlinger::onMessageReceived(int32_t what, int64_t vsyncId, nsecs_t expectedVSyncTime) {
    switch (what) {
        case MessageQueue::INVALIDATE: {
            onMessageInvalidate(vsyncId, expectedVSyncTime);
            break;
        }
        case MessageQueue::REFRESH: {
            onMessageRefresh();
            break;
        }
    }
}

网上很多文章都是从SurfaceFlinger::onMessageReceived

surfaceflinger绘制流程小结
本节主要讲两个部分
第一部分:app的layer如何和surfaceflinger连接起来
第二部分:vsync分发流程
Vsync流程
1、代码流程从如何从HWC接收Vsync信号开始
2、initScheduler初始化部分、app请求Vsync、app接收Vsync、surfaceflinger接收Vysnc 四个部分流程结合
3、EventThread监听Vsync、connection建立连接、Choreographer衔接app和surfaceflinger、Dispatcher分发vsync
4、这里挑选的都是vsync比较主线的几个流程,理清他们,理解vsync分发应该没问题。
5、还有一个从hwc传递vsync到eventthread这个流程有兴趣的可以自己去阅读一下源码
整条线:
app startactivity时创建surface和底层layer的连接,app开始绘制时请求下一个vysnc信号,vsync信号分发回app,app开始把视图绘制到layer,最后送显

五、写在最后

本文主要讲了文章开头提到的,surfaceflinger的初始化,底层handler消息机制,surfaceflinger的绘制流程(surface和layer连接&vsync分发)。希望通过本篇文章,能对surfaceflinger总体有个清晰的认知。

read the fucking source code!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容