RenderThread的創(chuàng)建流程

RenderThread的創(chuàng)建流程

本文基于android11的源碼

RenderThread 創(chuàng)建的一條路徑

要想知道RenderThread是怎么創(chuàng)建的,最快的辦法就是在創(chuàng)建線程代碼中打印一下調(diào)用棧

//frameworks/base/libs/hwui/renderthread/RenderThread.cpp
RenderThread::RenderThread()
        : ThreadBase()
        , mVsyncSource(nullptr)
        , mVsyncRequested(false)
        , mFrameCallbackTaskPending(false)
        , mRenderState(nullptr)
        , mEglManager(nullptr)
        , mFunctorManager(WebViewFunctorManager::instance())
        , mVkManager(nullptr) {
    Properties::load();
    //調(diào)試加的打印堆棧的地方
    dump_stack();
    //啟動RenderThread線程
    start("RenderThread");
}

最終打印出來的堆棧

TAG     : #00 pc 0000000000371674  /system/lib64/libhwui.so (dump_stack()+68)
TAG     : #01 pc 000000000037157a  /system/lib64/libhwui.so (android::uirenderer::renderthread::RenderThread::RenderThread()+234)
TAG     : #02 pc 00000000003713bf  /system/lib64/libhwui.so (android::uirenderer::renderthread::RenderThread::getInstance()+63)
TAG     : #03 pc 00000000003e28be  /system/lib64/libhwui.so (android::uirenderer::renderthread::RenderProxy::preload()+30)
TAG     : #04 pc 0000000000183ec7  /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+215)
TAG     : #05 pc 000000000017060a  /apex/com.android.art/lib64/libart.so
TAG     : #06 pc 00000000001983b8  /system/framework/framework.jar (android.app.ActivityThread.handleLaunchActivity+76)
TAG     : #07 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
TAG     : #08 pc 000000000028e02e  /system/framework/framework.jar (android.app.servertransaction.LaunchActivityItem.execute+134)
TAG     : #09 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
TAG     : #10 pc 0000000000290232  /system/framework/framework.jar (android.app.servertransaction.TransactionExecutor.executeCallbacks+154)
TAG     : #11 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
TAG     : #12 pc 000000000029016e  /system/framework/framework.jar (android.app.servertransaction.TransactionExecutor.execute+146)
TAG     : #13 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
TAG     : #14 pc 0000000000197734  /system/framework/framework.jar (android.app.ActivityThread$H.handleMessage+96)
TAG     : #15 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
TAG     : #16 pc 000000000036f2ae  /system/framework/framework.jar (offset 0x92b000) (android.os.Handler.dispatchMessage+38)
...

關(guān)鍵的幾個步驟應(yīng)該是沒打印出來,純粹受限于dump_stack函數(shù)的實現(xiàn),只能看出啟動RenderThread是在主線程,發(fā)生在handleLaunchActivity流程看起流程中。
抓了一份activity啟動的profile:am start-activity --start-profiler /data/local/tmp/123.trace --sampling 10 -n com.android.gallery3d/.app.GalleryActivity,如下圖

5CC6DAAD-9A77-4D47-947B-C71F766C3F52.png

猜測堆棧未打印出來的部分應(yīng)該就是android.graphics.HardwareRenderer.preload()以及調(diào)入native層的JNI函數(shù)。
先從handleLaunchActivity流程看起

//frameworks/base/core/java/android/app/ActivityThread.java
public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        ...
        // Initialize before creating the activity
        if (!ThreadedRenderer.sRendererDisabled
                && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
            HardwareRenderer.preload();
        }
        ...
    }

在app進(jìn)程的第一個Activity創(chuàng)建前,進(jìn)行ActivityInfo.FLAG_HARDWARE_ACCELERATED判斷,以及靜態(tài)成員ThreadedRenderer.sRendererDisabled進(jìn)行真假判斷,符合條件后調(diào)用HardwareRenderer.preload()函數(shù),該函數(shù)是native函數(shù)。ThreadedRenderer.sRendererDisabled是代碼邏輯設(shè)置ThreadedRenderer.disable()函數(shù)被調(diào)用的時候會判斷失敗,代碼全局搜索只發(fā)現(xiàn)public static ActivityThread systemMain()函數(shù)中調(diào)用了,表示只有systemserver進(jìn)程會判斷失敗。ActivityInfo.FLAG_HARDWARE_ACCELERATED表示app是否使用硬件加速,一般是在AndroidManifest.xml中聲明,或者android版本大于4.1等條件。暫且不關(guān)注這個細(xì)節(jié),大部分應(yīng)用應(yīng)該都是會使用硬件加速的。

//frameworks/base/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
static void android_view_ThreadedRenderer_preload(JNIEnv*, jclass) {
    RenderProxy::preload();
}

//frameworks/base/libs/hwui/renderthread/RenderProxy.cpp
void RenderProxy::preload() {
    // Create RenderThread object and start the thread. Then preload Vulkan/EGL driver. 
    //單例模式保證只會啟動一個RenderThread
    auto& thread = RenderThread::getInstance();
    thread.queue().post([&thread]() { thread.preload(); });
}

當(dāng)然,RenderThread創(chuàng)建的路徑不止上面描述這一種情況,但是走android_graphics_HardwareRenderer.cpp中創(chuàng)建RenderProxy對象,有RenderProxy來創(chuàng)建RenderThread,RenderProxy.cpp文件中對RenderThread對象的使用都是單例方法RenderThread::getInstance()的調(diào)用,可以保證只有一個RenderThread被啟動。

//frameworks/base/libs/hwui/renderthread/RenderThread.cpp
RenderThread& RenderThread::getInstance() {
    // This is a pointer because otherwise __cxa_finalize
    // will try to delete it like a Good Citizen but that causes us to crash
    // because we don't want to delete the RenderThread normally.
    static RenderThread* sInstance = new RenderThread();
    gHasRenderThreadInstance = true;
    return *sInstance;
}

RenderThread::RenderThread()
        : ThreadBase()
        , mVsyncSource(nullptr)
        , mVsyncRequested(false)
        , mFrameCallbackTaskPending(false)
        , mRenderState(nullptr)
        , mEglManager(nullptr)
        , mFunctorManager(WebViewFunctorManager::instance())
        , mVkManager(nullptr) {
    Properties::load();
    start("RenderThread");
}

RenderThread線程體

RenderThread繼承至Thread類,調(diào)用start函數(shù)后會啟動線程,入口函數(shù)為threadLoop

//frameworks/base/libs/hwui/renderthread/RenderThread.cpp
bool RenderThread::threadLoop() {
    setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
    //設(shè)置looper對象
    Looper::setForThread(mLooper);
    if (gOnStartHook) {
        gOnStartHook("RenderThread");
    }
    
    //主要看這個,初始化線程私有數(shù)據(jù)
    initThreadLocals();

    while (true) {
        waitForWork();
        processQueue();

        ...//省略一些請求nextVSYNC的邏輯

    return false;
}

RenderThread線程的線程私有變量中也有一個Choreographer(native Choreographer),Java層也有一個Choreographer,對象是放在主線程的ThreadLocal里面的,挺有意思。

void RenderThread::initThreadLocals() {
    setupFrameInterval();
    initializeChoreographer();
    mEglManager = new EglManager();
    mRenderState = new RenderState(*this);
    mVkManager = new VulkanManager();
    mCacheManager = new CacheManager();
}

跟 java層編舞者初始化類似,也有把fd加入到Looper中監(jiān)控的邏輯,不知道此fd是否彼fd

void RenderThread::initializeChoreographer() {
    LOG_ALWAYS_FATAL_IF(mVsyncSource, "Initializing a second Choreographer?");

    //正常app進(jìn)程,android系統(tǒng)正常模式都是會判斷成功的
    if (!Properties::isolatedProcess) {
        mChoreographer = AChoreographer_create();
        LOG_ALWAYS_FATAL_IF(mChoreographer == nullptr, "Initialization of Choreographer failed");
        AChoreographer_registerRefreshRateCallback(mChoreographer,
                                                   RenderThread::refreshRateCallback, this);

        // Register the FD
        mLooper->addFd(AChoreographer_getFd(mChoreographer), 0, Looper::EVENT_INPUT,
                       RenderThread::choreographerCallback, this);
        mVsyncSource = new ChoreographerSource(this);
    } else {
        mVsyncSource = new DummyVsyncSource(this);
    }
}

使用AChoreographer_create創(chuàng)建native Choreographer

//frameworks/native/libs/nativedisplay/AChoreographer.cpp
AChoreographer* AChoreographer_create() {
    Choreographer* choreographer = new Choreographer(nullptr);
    status_t result = choreographer->initialize();
    if (result != OK) {
        ALOGW("Failed to initialize");
        return nullptr;
    }
    return Choreographer_to_AChoreographer(choreographer);
}

//Choreographer繼承至DisplayEventDispatcher
class Choreographer : public DisplayEventDispatcher, public MessageHandler {
public:
    explicit Choreographer(const sp<Looper>& looper) EXCLUDES(gChoreographers.lock);
...
};

Choreographer::Choreographer(const sp<Looper>& looper)
      : DisplayEventDispatcher(looper, ISurfaceComposer::VsyncSource::eVsyncSourceApp,
                               ISurfaceComposer::ConfigChanged::eConfigChangedSuppress),
        mLooper(looper),
        mThreadId(std::this_thread::get_id()) {
    std::lock_guard<std::mutex> _l(gChoreographers.lock);
    gChoreographers.ptrs.push_back(this);
}

Choreographer居然是繼承至DisplayEventDispatcher,而且構(gòu)造函數(shù)調(diào)用了父類DisplayEventDispatcher構(gòu)造器,這跟java層編舞者分析過程中的NativeDisplayEventReceiver一樣,那不是會走一次跟surfaceflinger建立VSYNC通道的流程嗎?
在代碼中加了打印堆棧如下

DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource,
                                           ISurfaceComposer::ConfigChanged configChanged) {
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr) {
        //調(diào)試加堆棧打印
        dump_stack();
        mEventConnection = sf->createDisplayEventConnection(vsyncSource, configChanged);
        if (mEventConnection != nullptr) {
            mDataChannel = std::make_unique<gui::BitTube>();
            mEventConnection->stealReceiveChannel(mDataChannel.get());
        }
    }
}

輸出確實一個進(jìn)程會有倆次sf->createDisplayEventConnection以及mEventConnection->stealReceiveChannel(mDataChannel.get());

12-18 17:19:03.926  4779  4809 D TAG     : #00 pc 000000000009c1aa  /system/lib64/libgui.so (android::DisplayEventReceiver::DisplayEventReceiver(android::ISurfaceComposer::VsyncSource, android::ISurfaceComposer::ConfigChanged)+122)
12-18 17:19:03.926  4779  4809 D TAG     : #01 pc 000000000009bbf3  /system/lib64/libgui.so (android::DisplayEventDispatcher::DisplayEventDispatcher(android::sp<android::Looper> const&, android::ISurfaceComposer::VsyncSource, android::ISurfaceComposer::ConfigChanged)+83)
12-18 17:19:03.926  4779  4809 D TAG     : #02 pc 0000000000009ae1  /system/lib64/libnativedisplay.so (android::Choreographer::Choreographer(android::sp<android::Looper> const&)+65)
12-18 17:19:03.926  4779  4809 D TAG     : #03 pc 000000000000af22  /system/lib64/libnativedisplay.so (AChoreographer_create+50)
12-18 17:19:03.926  4779  4809 D TAG     : #04 pc 0000000000327b89  /system/lib64/libhwui.so (android::uirenderer::renderthread::RenderThread::initializeChoreographer()+41)
12-18 17:19:03.926  4779  4809 D TAG     : #05 pc 0000000000327a2a  /system/lib64/libhwui.so (android::uirenderer::renderthread::RenderThread::initThreadLocals()+58)
12-18 17:19:03.926  4779  4809 D TAG     : #06 pc 000000000032724f  /system/lib64/libhwui.so (android::uirenderer::renderthread::RenderThread::threadLoop()+63)
12-18 17:19:03.926  4779  4809 D TAG     : #07 pc 00000000000160f9  /system/lib64/libutils.so (android::Thread::_threadLoop(void*)+313)
12-18 17:19:03.926  4779  4809 D TAG     : #08 pc 0000000000015980  /system/lib64/libutils.so (thread_data_t::trampoline(thread_data_t const*)+416)
12-18 17:19:03.926  4779  4809 D TAG     : #09 pc 00000000000c7d5a  /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+58)
12-18 17:19:03.926  4779  4809 D TAG     : #10 pc 000000000005f0c7  /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+55)



12-18 17:19:04.152  4779  4779 D TAG     : #00 pc 000000000009c1aa  /system/lib64/libgui.so (android::DisplayEventReceiver::DisplayEventReceiver(android::ISurfaceComposer::VsyncSource, android::ISurfaceComposer::ConfigChanged)+122)
12-18 17:19:04.153  4779  4779 D TAG     : #01 pc 000000000009bbf3  /system/lib64/libgui.so (android::DisplayEventDispatcher::DisplayEventDispatcher(android::sp<android::Looper> const&, android::ISurfaceComposer::VsyncSource, android::ISurfaceComposer::ConfigChanged)+83)
12-18 17:19:04.153  4779  4779 D TAG     : #02 pc 00000000000f84ce  /system/lib64/libandroid_runtime.so (android::NativeDisplayEventReceiver::NativeDisplayEventReceiver(_JNIEnv*, _jobject*, android::sp<android::MessageQueue> const&, int, int)+110)
12-18 17:19:04.153  4779  4779 D TAG     : #03 pc 00000000000f8b70  /system/lib64/libandroid_runtime.so (android::nativeInit(_JNIEnv*, _jclass*, _jobject*, _jobject*, int, int)+112)
12-18 17:19:04.153  4779  4779 D TAG     : #04 pc 0000000000183ec7  /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+215)
12-18 17:19:04.153  4779  4779 D TAG     : #05 pc 000000000017060a  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #06 pc 00000000001ee6d0  /system/framework/framework.jar (offset 0x125d000) (android.view.DisplayEventReceiver.<init>+48)
12-18 17:19:04.153  4779  4779 D TAG     : #07 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #08 pc 00000000001ea73a  /system/framework/framework.jar (offset 0x125d000) (android.view.Choreographer$FrameDisplayEventReceiver.<init>+6)
12-18 17:19:04.153  4779  4779 D TAG     : #09 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #10 pc 00000000001eac1c  /system/framework/framework.jar (offset 0x125d000) (android.view.Choreographer.<init>+72)
12-18 17:19:04.153  4779  4779 D TAG     : #11 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #12 pc 00000000001eac98  /system/framework/framework.jar (offset 0x125d000) (android.view.Choreographer.<init>)
12-18 17:19:04.153  4779  4779 D TAG     : #13 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #14 pc 00000000001ea434  /system/framework/framework.jar (offset 0x125d000) (android.view.Choreographer$1.initialValue+20)
12-18 17:19:04.153  4779  4779 D TAG     : #15 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #16 pc 00000000001ea470  /system/framework/framework.jar (offset 0x125d000) (android.view.Choreographer$1.initialValue)
12-18 17:19:04.153  4779  4779 D TAG     : #17 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #18 pc 00000000000ea95c  /apex/com.android.art/javalib/core-oj.jar (java.lang.ThreadLocal.setInitialValue)
12-18 17:19:04.153  4779  4779 D TAG     : #19 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #20 pc 00000000000ea92e  /apex/com.android.art/javalib/core-oj.jar (java.lang.ThreadLocal.get+38)
12-18 17:19:04.153  4779  4779 D TAG     : #21 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #22 pc 00000000001ea8d4  /system/framework/framework.jar (offset 0x125d000) (android.view.Choreographer.getInstance+4)
12-18 17:19:04.153  4779  4779 D TAG     : #23 pc 000000000016fed1  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #24 pc 0000000000241cc2  /system/framework/framework.jar (offset 0x125d000) (android.view.ViewRootImpl.<init>+1098)
12-18 17:19:04.153  4779  4779 D TAG     : #25 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #26 pc 0000000000241842  /system/framework/framework.jar (offset 0x125d000) (android.view.ViewRootImpl.<init>+10)
12-18 17:19:04.153  4779  4779 D TAG     : #27 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #28 pc 000000000026651a  /system/framework/framework.jar (offset 0x125d000) (android.view.WindowManagerGlobal.addView+342)
12-18 17:19:04.153  4779  4779 D TAG     : #29 pc 0000000000171224  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #30 pc 000000000026738e  /system/framework/framework.jar (offset 0x125d000) (android.view.WindowManagerImpl.addView+42)
12-18 17:19:04.153  4779  4779 D TAG     : #31 pc 0000000000171d7a  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #32 pc 00000000001c820c  /system/framework/framework.jar (android.app.Dialog.show+268)
12-18 17:19:04.153  4779  4779 D TAG     : #33 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #34 pc 00000000001ac610  /system/framework/framework.jar (android.app.AlertDialog$Builder.show+8)
12-18 17:19:04.153  4779  4779 D TAG     : #35 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #36 pc 000000000007fd68  /data/dalvik-cache/x86_64/system@product@app@Gallery2@Gallery2.apk@classes.vdex (com.android.gallery3d.app.AbstractGalleryActivity.onStart+124)
12-18 17:19:04.153  4779  4779 D TAG     : #37 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #38 pc 00000000002120e0  /system/framework/framework.jar (android.app.Instrumentation.callActivityOnStart)
12-18 17:19:04.153  4779  4779 D TAG     : #39 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #40 pc 00000000001a9e32  /system/framework/framework.jar (android.app.Activity.performStart+54)
12-18 17:19:04.153  4779  4779 D TAG     : #41 pc 0000000000170b5d  /apex/com.android.art/lib64/libart.so
12-18 17:19:04.153  4779  4779 D TAG     : #42 pc 00000000001a0a2a  /system/framework/framework.jar (android.app.ActivityThread.handleStartActivity+62)
...

那看起來可以得出一個結(jié)論:主線程擁有的java層Choreographer對象,會跟sf建立EventConnection,并且形成一條Bitube socket通道。RenderThread線程擁有的Native層Choreographer對象也會跟sf建立EventConnection,并且形成一條Bitube socket通道。那主線程和RenderThread線程都有獨立接收vsync信號的能力了。

主線程的VSYNC會調(diào)到j(luò)ava層Choreographer.doFrame(),RenderThread線程接收到VSYNC會如何呢?RenderThread::initializeChoreographer()流程中也有

// Register the FD
        mLooper->addFd(AChoreographer_getFd(mChoreographer), 0, Looper::EVENT_INPUT,
                       RenderThread::choreographerCallback, this);

意味著RenderThread線程收到VSYNC后會回調(diào)RenderThread::choreographerCallback

//frameworks/base/libs/hwui/renderthread/RenderThread.cpp
int RenderThread::choreographerCallback(int fd, int events, void* data) {
    ...
    RenderThread* rt = reinterpret_cast<RenderThread*>(data);
    AChoreographer_handlePendingEvents(rt->mChoreographer, data);

    return 1;
}


//frameworks/native/libs/nativedisplay/AChoreographer.cpp
void AChoreographer_handlePendingEvents(AChoreographer* choreographer, void* data) {
    ...
    Choreographer* impl = AChoreographer_to_Choreographer(choreographer);
    impl->handleEvent(-1, Looper::EVENT_INPUT, data);
}

//調(diào)到Choreographer父類DisplayEventDispatcher的handleEvent方法

int DisplayEventDispatcher::handleEvent(int, int events, void*) {
    ...

    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
        ...
        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
    }

    return 1; // keep the callback
}

最后還是調(diào)回Choreographer::dispatchVsync

//frameworks/native/libs/nativedisplay/AChoreographer.cpp
void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t) {
    std::vector<FrameCallback> callbacks{};
    {
        std::lock_guard<std::mutex> _l{mLock};
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        while (!mFrameCallbacks.empty() && mFrameCallbacks.top().dueTime < now) {
            callbacks.push_back(mFrameCallbacks.top());
            mFrameCallbacks.pop();
        }
    }
    for (const auto& cb : callbacks) {
        if (cb.callback64 != nullptr) {
            cb.callback64(timestamp, cb.data);
        } else if (cb.callback != nullptr) {
            cb.callback(timestamp, cb.data);
        }
    }
}

調(diào)了mFrameCallbacks中符合條件的callback,那看看mFrameCallbacks是怎么維護(hù)的,只有一個地方對這個vector進(jìn)行了添加操作

void Choreographer::postFrameCallbackDelayed(
        AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay) {
    ...
    FrameCallback callback{cb, cb64, data, now + delay};
    {
        std::lock_guard<std::mutex> _l{mLock};
        mFrameCallbacks.push(callback);
    }
    ...
}

那么其實就是回調(diào)了postFrameCallbackDelayed傳入的函數(shù)指針?biāo)赶虻暮瘮?shù)了
全局搜索就只有RenderThread.cpp中有調(diào)用,所以最后回調(diào)的函數(shù)大可能就是RenderThread::frameCallback

class ChoreographerSource : public VsyncSource {
public:
    ...
    virtual void requestNextVsync() override {
        AChoreographer_postFrameCallback64(mRenderThread->mChoreographer,
                                           RenderThread::frameCallback, mRenderThread);
    }
...
};

void RenderThread::frameCallback(int64_t frameTimeNanos, void* data) {
    RenderThread* rt = reinterpret_cast<RenderThread*>(data);
    rt->mVsyncRequested = false;
    if (rt->timeLord().vsyncReceived(frameTimeNanos) && !rt->mFrameCallbackTaskPending) {
        ATRACE_NAME("queue mFrameCallbackTask");
        rt->mFrameCallbackTaskPending = true;
        nsecs_t runAt = (frameTimeNanos + rt->mDispatchFrameDelay);
        rt->queue().postAt(runAt, [=]() { rt->dispatchFrameCallbacks(); });
    }
}

接下來就是在renthread的loop中調(diào)用dispatchFrameCallbacks

void RenderThread::dispatchFrameCallbacks() {
    ATRACE_CALL();
    mFrameCallbackTaskPending = false;

    std::set<IFrameCallback*> callbacks;
    mFrameCallbacks.swap(callbacks);

    if (callbacks.size()) {
        // Assume one of them will probably animate again so preemptively
        // request the next vsync in case it occurs mid-frame
        requestVsync();
        for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end();
             it++) {
            (*it)->doFrame();
        }
    }
}

只有frameworks/base/libs/hwui/renderthread/CanvasContext.h中的CanvasContext繼承了IFrameCallback,也就是說回調(diào)的是CanvasContext::doFrame()

//frameworks/base/libs/hwui/renderthread/CanvasContext.cpp
// Called by choreographer to do an RT-driven animation
void CanvasContext::doFrame() {
    if (!mRenderPipeline->isSurfaceReady()) return;
    prepareAndDraw(nullptr);
}

void CanvasContext::prepareAndDraw(RenderNode* node) {
    ...

    TreeInfo info(TreeInfo::MODE_RT_ONLY, *this);
    prepareTree(info, frameInfo, systemTime(SYSTEM_TIME_MONOTONIC), node);
    if (info.out.canDrawThisFrame) {
        draw();
    } else {
        // wait on fences so tasks don't overlap next frame
        waitOnFences();
    }
}

...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容