Android graphics(三) surfaceflinger

一刻恭、前言

本文主要內(nèi)容
1、surfaceflinger初始化流程季惯;
2吠各、surfaceflinger消息機(jī)制臀突;
3勉抓、surfaceflinger繪制流程;
4候学、VSync分發(fā)流程

surfaceFlinger由init進(jìn)程啟動(dòng)藕筋,獨(dú)立進(jìn)程運(yùn)行,它接受來(lái)自多個(gè)來(lái)源的數(shù)據(jù)緩沖區(qū)梳码,對(duì)它們進(jìn)行合成隐圾,然后發(fā)送到顯示設(shè)備伍掀。
簡(jiǎn)述顯示過(guò)程
1>、一個(gè)頁(yè)面暇藏,一般分為三個(gè)window蜜笤,狀態(tài)欄、app和導(dǎo)航欄盐碱,每個(gè)window看作要顯示的一層把兔,windowManager顯示時(shí),請(qǐng)求surfaceflinger為每個(gè)window創(chuàng)建衣蛾surface(layer)來(lái)繪制顯示
每一個(gè)顯示layer層瓮顽,我們看作一個(gè)bufferqueue緩存隊(duì)列县好。surfaceflinger合成bufferqueue,合成后送到Hardware Composer顯示暖混。
2>缕贡、顯示按照一定刷新率更新畫(huà)面,手機(jī)平板通常為60fps(16.6ms顯示一次)拣播,一次刷新由vsync信號(hào)發(fā)起晾咪,surfaceflinger接收到信號(hào)后組織這一次刷新顯示。
3>诫尽、當(dāng) VSYNC 信號(hào)到達(dá)時(shí)禀酱,SurfaceFlinger 會(huì)遍歷它的層列表,以尋找新的緩沖區(qū)牧嫉。如果找到新的緩沖區(qū)剂跟,它會(huì)獲取該緩沖區(qū);
否則酣藻,它會(huì)繼續(xù)使用以前獲取的緩沖區(qū)曹洽。SurfaceFlinger 必須始終顯示內(nèi)容,因此它會(huì)保留一個(gè)緩沖區(qū)辽剧。如果在某個(gè)層上沒(méi)有提交緩沖區(qū)送淆,則該層會(huì)被忽略。
備注:本文只列出關(guān)鍵代碼怕轿,關(guān)鍵流程偷崩。

二、surfaceflinger啟動(dòng)流程

2.1撞羽、main入口

surfaceflinger.rc由init.rc啟動(dòng)阐斜,main_surfaceflinger.cpp main函數(shù)為啟動(dòng)入口   

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

提煉其中重要三件事情,主要還是一個(gè)surfaceFlinger的創(chuàng)建
1诀紊、createSurfaceFlinger并init(伴隨onFirstRef)
2谒出、addService到上層
3、進(jìn)入消息循環(huán)

2.2、surfaceflinger構(gòu)造

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

SurfaceComposer繼承自BnSurfaceComposer笤喳,即為實(shí)現(xiàn)了ISurfaceComposer接口的Bn服務(wù)端;
Dump信息PriorityDumper为居;
死亡通知DeathRecipient,當(dāng)Binder服務(wù)端程序掛掉后杀狡,可以通知給綁定的Binder客戶端程序;
實(shí)現(xiàn)了HWC2的ComposerCallback回調(diào)蒙畴,監(jiān)聽(tīng)Composer HAL的一些事件,比如Hotplug, Vsync ...

2.3呜象、消息隊(duì)列SurfaceFlinger::onFirstRef

這里引出surfaceflinger重點(diǎn)之一surfaceflinger的消息隊(duì)列忍抽。后面單獨(dú)講
SurfaceFlinger繼承RefBase類,所以此處一旦new出對(duì)象賦給sp指針后董朝,將立刻觸發(fā)SurfaceFlinger類的onFirstRef方法的調(diào)用鸠项。

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


    // 創(chuàng)建HWComposer子姜,通過(guò)mCompositionEngine->setHwComposer設(shè)置對(duì)象屬性祟绊,并注冊(cè)回調(diào)
    mCompositionEngine->setTimeStats(mTimeStats);
    mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
    mCompositionEngine->getHwComposer().setCallback(this);
    ClientCache::getInstance().setRenderEngine(&getRenderEngine());


    // 任何初始熱插拔和顯示更改的結(jié)果
    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();


    // 開(kāi)啟一個(gè)設(shè)置屬性的線程
    if (mStartPropertySetThread->Start() != NO_ERROR) {
        ALOGE("Run StartPropertySetThread failed!");
    }
}

init方法主要做了這么幾件事情:
1、創(chuàng)建一個(gè)RenderEngine
2哥捕、創(chuàng)建HWComposer牧抽,通過(guò)mCompositionEngine->setHwComposer設(shè)置對(duì)象屬性,并注冊(cè)回調(diào)
3遥赚、處理Display顯示屏幕的熱插拔
4扬舒、初始化顯示設(shè)備
5、開(kāi)啟設(shè)置屬性線程

2.5凫佛、SurfaceFlinger::run

main函數(shù)中最后一步讲坎,run開(kāi)啟無(wú)限循環(huán)等待消息

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

2.5小結(jié)

上面五個(gè)小點(diǎn)總結(jié)了surfaceflinger的初始化過(guò)程。整體來(lái)說(shuō)初始化更多還是對(duì)象的創(chuàng)建愧薛,要更加深入的理解surfaceflinger晨炕,
我們還應(yīng)該剖析一些重要流程出來(lái)理解。這樣才有助于理解surfaceflinger在繪制過(guò)程中如何承上啟下

三毫炉、Surfaceflinger消息隊(duì)列

在surafceflinger的構(gòu)造函數(shù)中初始化

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消息隊(duì)列中,重要的兩個(gè)事件瞄勾,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;
    }
}

消息隊(duì)列又處理回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;
        }
    }
}

這里摘錄一個(gè)bufferqueue的acquireBuffer方法時(shí)的堆棧
vsync刷新信號(hào)過(guò)來(lái)onMessageReceived收到消息后费奸,bufferqueue開(kāi)始處理圖像隊(duì)列

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創(chuàng)建surface流程

4.1.1愿阐、wms和surfaceflinger建立連接

要顯示的頁(yè)面通過(guò)window告訴surfaceflinger創(chuàng)建surface來(lái)繪圖,這個(gè)surface就是一個(gè)layer(layer的核心就是buffer queue)四濒;
surfaceflinger創(chuàng)建的bufferqueue不會(huì)傳遞到app换况,而是通過(guò)內(nèi)存共享直接供app繪制。bufferqueue都不會(huì)傳遞盗蟆;
那么這一節(jié)內(nèi)容我們來(lái)講講這個(gè)流程

//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方法只是調(diào)用initCheck檢查了一下
}

上面截取了一段流程代碼:
1>戈二、從我們熟知的addwindow開(kāi)始,WindowSate表示一個(gè)window喳资;
2>觉吭、mSurfaceSession表示一個(gè)跟surfaceflinger的連接,其中SurfaceComposerClient就是表示連接的指針仆邓;
3>鲜滩、最后創(chuàng)建的Client實(shí)現(xiàn)ISurfaceComposerClient的aidl,它可以創(chuàng)建Surface节值,并且維護(hù)一個(gè)應(yīng)用程序的所有Layer徙硅;

4.1.2、Surface創(chuàng)建對(duì)應(yīng)Layer

// ViewRootImpl.java
public final Surface mSurface = new Surface();
一個(gè)ViewRootImpl對(duì)應(yīng)一個(gè)Surface(上層surface),而Surface 在 SurfaceFlinger 中對(duì)應(yīng)的實(shí)體是 Layer 對(duì)象搞疗。  
1>嗓蘑、一個(gè)Vsync信號(hào)(vysnc發(fā)起頁(yè)面刷新流程)執(zhí)行ViewRootImpl.performTraversals    

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


private int relayoutWindow(...) throws RemoteException {
    // 最后一個(gè)參數(shù) mSurface 就是之前創(chuàng)建的 Surface 對(duì)象
    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;
}

上面這一段主要是為了說(shuō)明relayoutWindow會(huì)createSurfaceControl
2>、surface的layer創(chuàng)建由SurfaceControl來(lái)進(jìn)行

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建立連接時(shí)的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);
}

這里來(lái)來(lái)回回最后還是SurfaceComposerClient指針組織了createSurface匿乃,即創(chuàng)建了surface對(duì)應(yīng)的layer

4.1.3桩皿、上層surface和Layer對(duì)應(yīng)起來(lái)

createSurfaceControl創(chuàng)建了layer,接著立馬getSurface創(chuàng)建對(duì)應(yīng)關(guān)系
因?yàn)樯蠈觿?chuàng)建的surface還是一個(gè)空的對(duì)象幢炸,copyFrom等于就是填充了surface的內(nèi)容
接上面4.1.2中createSurfaceControl方法中的surfaceController.getSurface(outSurface)

// outSurface是上層ViewRootImpl創(chuàng)建的surface
void getSurface(Surface outSurface) {
    outSurface.copyFrom(mSurfaceControl);
}


// Surface.java
public void copyFrom(SurfaceControl other) {
    long surfaceControlPtr = other.mNativeObject;
    // mNativeObject是4.2.2 小結(jié) SurfaceControl創(chuàng)建時(shí)返回的指針
    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指針和底層指針的轉(zhuǎn)換
    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 是上面創(chuàng)建的 gbp 對(duì)象
    // 這里new surface實(shí)際是底層的surface
    mSurfaceData = new Surface(mGraphicBufferProducer, false);
    return mSurfaceData;
}

1泄隔、nativeGetFromSurfaceControl 返回native Suface的指針,指針的值賦給SurfaceControl.mNativeObject
2宛徊、上層surface調(diào)用copyFrom填充內(nèi)容時(shí)佛嬉,實(shí)際就是拿到了SurfaceControl了,也擁有了底層的surface指針闸天,子集關(guān)系巷燥。

4.2、Vysnc流程

4.2.1 幾點(diǎn)概念

1号枕、VSYNC 信號(hào)可同步顯示流水線缰揪。顯示流水線由應(yīng)用渲染、SurfaceFlinger 合成以及用于在屏幕上顯示圖像的硬件混合渲染器 (HWC) 組成葱淳。
2钝腺、VSYNC 可同步應(yīng)用喚醒以開(kāi)始渲染的時(shí)間、SurfaceFlinger 喚醒以合成屏幕的時(shí)間以及屏幕刷新周期赞厕。這種同步可以消除卡頓艳狐,并提升圖形的視覺(jué)表現(xiàn)。
3皿桑、vysnc的引入毫目,可以及時(shí)的告知cpu/gpu暫停別的事情蔬啡,及時(shí)處理顯示的這一幀。從而減少卡頓發(fā)生镀虐。
4箱蟆、三級(jí)緩存:vsync+三級(jí)緩存,當(dāng)?shù)趎+1處理不過(guò)來(lái)的時(shí)候刮便,由于有三次緩存數(shù)據(jù)空猜,即使n+1卡頓,或者n+1和n+2卡頓恨旱,只要沒(méi)有連著卡三次辈毯,都有緩存可以拿,UI上就不會(huì)造成卡頓搜贤。

4.2.2 DispSync

DispSync 維護(hù)屏幕基于硬件的周期性 VSYNC 事件的模型


image.png

我們一共有三個(gè)信號(hào)谆沃,HW_VYNC_0 是硬件產(chǎn)生的同步信號(hào)
DispSync則負(fù)責(zé)產(chǎn)生由Choreographer 和 SurfaceFlinger 使用的 VSYNC 和 SF_VSYNC 信號(hào),不管是否接收到HW_VYSNC_0都會(huì)產(chǎn)生仪芒,HW_VYSNC_0只是起到參考作用

4.2.3 Vync的偏移

image.png

HW_VSYNC_0 - 屏幕開(kāi)始顯示下一幀管毙。
VSYNC - 應(yīng)用讀取輸入內(nèi)容并生成下一幀。
SF_VSYNC - SurfaceFlinger 開(kāi)始為下一幀進(jìn)行合成
VSYNC_EVENT_PHASE_OFFSET_NS 和 SF_VSYNC_EVENT_PHASE_OFFSET_NS 對(duì)應(yīng)phase-app和phase-sf桌硫,默認(rèn)都為0

偏移量的加入是為了減少延遲夭咬,我們以正常情況來(lái)講,一幀16.6ms就能渲染完成铆隘。App可以在phase-sf - phase-app時(shí)間內(nèi)完成繪制卓舵,SurfaceFlinger可以在VSync周期 - phase-sf時(shí)間內(nèi)完成合成,那么在下一個(gè)VSync信號(hào)時(shí)就可以上屏膀钠,即幀延遲為16ms掏湾。這樣理想情況下,延遲就被控制成了一幀肿嘲。
如果app繪制超時(shí)融击,sf就會(huì)在下一幀繪制,增加了一幀的周期雳窟。所以一般情況下尊浪,系統(tǒng)都會(huì)將phase-sf - phase-app設(shè)置為VSync周期。這樣不管出現(xiàn)怎樣的延遲現(xiàn)象封救,sf的延遲周期都是控制為一幀一幀的增加拇涤。

4.2.4 Vync代碼流程

簡(jiǎn)述整個(gè)過(guò)程:
1、整個(gè)Vsync流程是從HWC監(jiān)聽(tīng)硬件產(chǎn)生的Vsync開(kāi)始誉结,由DispSync維護(hù)VSYNC模型鹅士,Vsync信號(hào)是一直存在的。
2惩坑、app請(qǐng)求vsync
一個(gè)頁(yè)面并不是無(wú)時(shí)無(wú)刻都在刷新掉盅,當(dāng)觸摸view發(fā)生變化也拜,請(qǐng)求焦點(diǎn),開(kāi)始動(dòng)畫(huà)或者startActivity等等時(shí)趾痘,ViewRootImpl會(huì)調(diào)用scheduleTraversals流程慢哈,這個(gè)流程會(huì)讓app接收下一個(gè)Vsync信號(hào)。
就是不管哪個(gè)方式刷新view都是scheduleTraversals來(lái)觸發(fā)

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

3扼脐、app接收vsync
收到信號(hào)后會(huì)控制view通過(guò)performTraversals方法繪制三大流程

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

4.2.4.1 Vsync初始化

分幾個(gè)部分:
1、initScheduler 初始化vysnc機(jī)制
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信號(hào)事件
    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方法注冊(cè)回調(diào)開(kāi)始,注冊(cè)回調(diào)會(huì)立馬觸發(fā)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初始開(kāi)始的地方懈叹,代碼是從surfaceflinger::init開(kāi)始轿偎,給HWC setCallback,直接回調(diào)hotplag熱插拔罚攀,開(kāi)始Scheduler的初始化
接下來(lái)就是initScheduler具體內(nèi)容:

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

    // 創(chuàng)建Scheduler對(duì)象
    mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this);
    const auto configs = mVsyncConfiguration->getCurrentConfigs();
    const nsecs_t vsyncPeriod = currRefreshRate.getPeriodNsecs();
    //創(chuàng)建一個(gè)名字為app的connection
     mAppConnectionHandle =
            mScheduler->createConnection("app", mFrameTimeline->getTokenManager(),
                                         /*workDuration=*/configs.late.appWorkDuration,
                                         /*readyDuration=*/configs.late.sfWorkDuration,
                                         impl::EventThread::InterceptVSyncsCallback());
    //創(chuàng)建一個(gè)名字為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主要作用是綁定一個(gè)回調(diào)函數(shù) MessageQueue::vsyncCallback 到VSyncDispatch上雌澄,回調(diào)名字"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));
}

簡(jiǎn)述流程:
1斋泄、HwComposer注冊(cè)回調(diào)會(huì)立馬觸發(fā)onComposerHalHotplug方法,熱插拔立馬initScheduler
2镐牺、配置fps炫掐、刷新周期、Vsync信息睬涧、app/sf偏移量募胃、創(chuàng)建Scheduler、sf/appSf/app 三個(gè)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)};
}

創(chuàng)建VSyncTracker畦浓、VSyncDispatch痹束、VsyncController封裝到VsyncSchedule并返回

名稱 作用
VSyncTracker 根據(jù)硬件的Vysnc、歷史數(shù)據(jù)建立一個(gè)Vsync模型讶请,預(yù)測(cè)Vsync信號(hào)
VSyncDispatch 分發(fā)Vsync回調(diào)
VsyncController 配合tracker采樣
Connection app,appSf,sf三個(gè)監(jiān)聽(tīng)vysnc

初始化部分主要介紹創(chuàng)建了哪些東西祷嘶,vysnc運(yùn)行機(jī)制的相關(guān)主角基本都列出來(lái)了。接下來(lái)我們先講App請(qǐng)求Vsync和app接收Vsync夺溢。然后講解Vsync的運(yùn)作抹蚀。

4.2.4.2、App請(qǐng)求Vsync

前面有簡(jiǎn)單提到app怎么開(kāi)始請(qǐng)求vsync:

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

本文介紹的重點(diǎn)是surfaceflinger企垦,所以我們來(lái)詳細(xì)看下請(qǐng)求這個(gè)過(guò)程环壤,surfaceflinger做了什么,java層也比較簡(jiǎn)單,跟著上面的流程去追一下就好钞诡。

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請(qǐng)求sync的流程郑现,主要還是一個(gè)間接調(diào)用湃崩。在mCondition.notify_all喚醒鎖后,繼續(xù)后邊的流程

4.2.4.3接箫、App接收Vsync

//EventThread.cpp 
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
    DisplayEventConsumers consumers;
    //1攒读、如果隊(duì)列不為空取一次vsync的event事件出來(lái)
    if (!mPendingEvents.empty()) {
            event = mPendingEvents.front();
            mPendingEvents.pop_front();
    ...
    //2、先取出一個(gè)connection ,然后用shouldConsumeEvent判斷是否發(fā)送到connection
    //這里無(wú)限循環(huán)辛友,會(huì)取出所有需要分發(fā)消息的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薄扁、前面兩個(gè)都滿足了consumers就不為空,就開(kāi)始分發(fā)
    if (!consumers.empty()) {
        dispatchEvent(*event, consumers);
        consumers.clear();
    }
    ...
    //4废累、上述兩個(gè)條件沒(méi)有滿足邓梅,會(huì)走到這里wait,直到有請(qǐng)求來(lái)notify喚醒邑滨,也就是上面的notify_all
    if (mState == State::Idle) {
        mCondition.wait(lock);
    }

1日缨、這樣EventThread就起到了一個(gè)有請(qǐng)求才會(huì)vsync的監(jiān)測(cè)作用。
2掖看、注意consumers是所有需要分發(fā)dispatchEvent的connection合集
3匣距、繼續(xù)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流程一層一層調(diào)用會(huì)通過(guò)BitTube來(lái)傳遞信息
2哎壳、BitTube用Linux/Unix中的socketpair進(jìn)行跨進(jìn)程數(shù)據(jù)傳遞毅待,
3、成員變量mReceiveFd,看起來(lái)是一個(gè)接收端,實(shí)際上這個(gè)fd也可以用來(lái)發(fā)送归榕,同樣mSendFd也可以用來(lái)接收恩静,只是BitTube是按照單向方式使用它的:一端寫(xiě)入數(shù)據(jù),另一端讀出數(shù)據(jù)
4蹲坷、這里我們可以簡(jiǎn)單理解為mSendFd用來(lái)發(fā)送驶乾,mReceiveFd對(duì)端用來(lái)接收。

//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取出一個(gè)有效的sync event
    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
        mWaitingForVsync = false;
        //分發(fā)
        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);
        // 調(diào)用到j(luò)ava層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請(qǐng)求级乐,有需要發(fā)送的connection,下一次vysnc event開(kāi)始dispatchevent
2县匠、dispatchevent間接由DisplayEventDispatcher來(lái)負(fù)責(zé)分發(fā)
3风科、分發(fā)時(shí),間接調(diào)用java層dispatchVsync乞旦,由上層控制繪制view

4.2.4.4贼穆、surfaceflinger接收Vsync

1、有了上面app收發(fā)兰粉,基本就理解vsync是怎么被分發(fā)出去了故痊。
2、在initScheduler流程時(shí)玖姑,實(shí)際我們創(chuàng)建了三個(gè)監(jiān)聽(tīng)app愕秫、appSf慨菱、sf,app就是app的收發(fā)戴甩,appSf這個(gè)監(jiān)聽(tīng)主要為surfaceflinger的工作線程服務(wù)符喝,sf則用來(lái)通知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;
        }
    }
}

網(wǎng)上很多文章都是從SurfaceFlinger::onMessageReceived

surfaceflinger繪制流程小結(jié)
本節(jié)主要講兩個(gè)部分
第一部分:app的layer如何和surfaceflinger連接起來(lái)
第二部分:vsync分發(fā)流程
Vsync流程
1甜孤、代碼流程從如何從HWC接收Vsync信號(hào)開(kāi)始
2协饲、initScheduler初始化部分、app請(qǐng)求Vsync缴川、app接收Vsync茉稠、surfaceflinger接收Vysnc 四個(gè)部分流程結(jié)合
3、EventThread監(jiān)聽(tīng)Vsync二跋、connection建立連接战惊、Choreographer銜接app和surfaceflinger流昏、Dispatcher分發(fā)vsync
4扎即、這里挑選的都是vsync比較主線的幾個(gè)流程,理清他們况凉,理解vsync分發(fā)應(yīng)該沒(méi)問(wèn)題谚鄙。
5、還有一個(gè)從hwc傳遞vsync到eventthread這個(gè)流程有興趣的可以自己去閱讀一下源碼
整條線:
app startactivity時(shí)創(chuàng)建surface和底層layer的連接刁绒,app開(kāi)始繪制時(shí)請(qǐng)求下一個(gè)vysnc信號(hào)闷营,vsync信號(hào)分發(fā)回app,app開(kāi)始把視圖繪制到layer知市,最后送顯

五傻盟、寫(xiě)在最后

本文主要講了文章開(kāi)頭提到的,surfaceflinger的初始化嫂丙,底層handler消息機(jī)制娘赴,surfaceflinger的繪制流程(surface和layer連接&vsync分發(fā))。希望通過(guò)本篇文章跟啤,能對(duì)surfaceflinger總體有個(gè)清晰的認(rèn)知诽表。

read the fucking source code!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市隅肥,隨后出現(xiàn)的幾起案子竿奏,更是在濱河造成了極大的恐慌,老刑警劉巖腥放,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泛啸,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡秃症,警方通過(guò)查閱死者的電腦和手機(jī)平痰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)汞舱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人宗雇,你說(shuō)我怎么就攤上這事昂芜。” “怎么了赔蒲?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵泌神,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我舞虱,道長(zhǎng)欢际,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任矾兜,我火速辦了婚禮损趋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘椅寺。我一直安慰自己浑槽,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布返帕。 她就那樣靜靜地躺著桐玻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪荆萤。 梳的紋絲不亂的頭發(fā)上镊靴,一...
    開(kāi)封第一講書(shū)人閱讀 49,842評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音链韭,去河邊找鬼偏竟。 笑死,一個(gè)胖子當(dāng)著我的面吹牛敞峭,可吹牛的內(nèi)容都是我干的踊谋。 我是一名探鬼主播,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼儡陨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼褪子!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起骗村,我...
    開(kāi)封第一講書(shū)人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嫌褪,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后胚股,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體笼痛,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了缨伊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摘刑。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖刻坊,靈堂內(nèi)的尸體忽然破棺而出枷恕,到底是詐尸還是另有隱情,我是刑警寧澤谭胚,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布徐块,位于F島的核電站,受9級(jí)特大地震影響灾而,放射性物質(zhì)發(fā)生泄漏胡控。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一旁趟、第九天 我趴在偏房一處隱蔽的房頂上張望昼激。 院中可真熱鬧,春花似錦锡搜、人聲如沸橙困。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纷宇。三九已至夸盟,卻和暖如春蛾方,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背上陕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工桩砰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人释簿。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓亚隅,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親庶溶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子煮纵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容