RenderThread的创建流程

RenderThread的创建流程

本文基于android11的源码

RenderThread 创建的一条路径

要想知道RenderThread是怎么创建的,最快的办法就是在创建线程代码中打印一下调用栈

//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();
    //调试加的打印堆栈的地方
    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)
...

关键的几个步骤应该是没打印出来,纯粹受限于dump_stack函数的实现,只能看出启动RenderThread是在主线程,发生在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

猜测堆栈未打印出来的部分应该就是android.graphics.HardwareRenderer.preload()以及调入native层的JNI函数。
先从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进程的第一个Activity创建前,进行ActivityInfo.FLAG_HARDWARE_ACCELERATED判断,以及静态成员ThreadedRenderer.sRendererDisabled进行真假判断,符合条件后调用HardwareRenderer.preload()函数,该函数是native函数。ThreadedRenderer.sRendererDisabled是代码逻辑设置ThreadedRenderer.disable()函数被调用的时候会判断失败,代码全局搜索只发现public static ActivityThread systemMain()函数中调用了,表示只有systemserver进程会判断失败。ActivityInfo.FLAG_HARDWARE_ACCELERATED表示app是否使用硬件加速,一般是在AndroidManifest.xml中声明,或者android版本大于4.1等条件。暂且不关注这个细节,大部分应用应该都是会使用硬件加速的。

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

当然,RenderThread创建的路径不止上面描述这一种情况,但是走android_graphics_HardwareRenderer.cpp中创建RenderProxy对象,有RenderProxy来创建RenderThread,RenderProxy.cpp文件中对RenderThread对象的使用都是单例方法RenderThread::getInstance()的调用,可以保证只有一个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类,调用start函数后会启动线程,入口函数为threadLoop

//frameworks/base/libs/hwui/renderthread/RenderThread.cpp
bool RenderThread::threadLoop() {
    setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
    //设置looper对象
    Looper::setForThread(mLooper);
    if (gOnStartHook) {
        gOnStartHook("RenderThread");
    }
    
    //主要看这个,初始化线程私有数据
    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中监控的逻辑,不知道此fd是否彼fd

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

    //正常app进程,android系统正常模式都是会判断成功的
    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创建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,而且构造函数调用了父类DisplayEventDispatcher构造器,这跟java层编舞者分析过程中的NativeDisplayEventReceiver一样,那不是会走一次跟surfaceflinger建立VSYNC通道的流程吗?
在代码中加了打印堆栈如下

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

输出确实一个进程会有俩次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)
...

那看起来可以得出一个结论:主线程拥有的java层Choreographer对象,会跟sf建立EventConnection,并且形成一条Bitube socket通道。RenderThread线程拥有的Native层Choreographer对象也会跟sf建立EventConnection,并且形成一条Bitube socket通道。那主线程和RenderThread线程都有独立接收vsync信号的能力了。

主线程的VSYNC会调到java层Choreographer.doFrame(),RenderThread线程接收到VSYNC会如何呢?RenderThread::initializeChoreographer()流程中也有

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

意味着RenderThread线程收到VSYNC后会回调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);
}

//调到Choreographer父类DisplayEventDispatcher的handleEvent方法

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

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

    return 1; // keep the callback
}

最后还是调回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);
        }
    }
}

调了mFrameCallbacks中符合条件的callback,那看看mFrameCallbacks是怎么维护的,只有一个地方对这个vector进行了添加操作

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

那么其实就是回调了postFrameCallbackDelayed传入的函数指针所指向的函数了
全局搜索就只有RenderThread.cpp中有调用,所以最后回调的函数大可能就是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中调用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,也就是说回调的是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();
    }
}

...

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

推荐阅读更多精彩内容