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,如下圖

猜測堆棧未打印出來的部分應(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();
}
}
...