相關(guān)文章鏈接:
1. Android Framework - 學(xué)習(xí)啟動(dòng)篇
2. 源碼閱讀分析 - Window底層原理與系統(tǒng)架構(gòu)
相關(guān)源碼文件:
/frameworks/base/core/java/android/view/ViewRootImpl.java
/frameworks/base/core/java/android/view/Choreographer.java
/frameworks/base/core/java/android/view/DisplayEventReceiver.java
/frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp
/frameworks/native/libs/gui/DisplayEventReceiver.cpp
/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
/frameworks/native/services/surfaceflinger/EventThread.cpp
/frameworks/native/libs/gui/BitTube.cpp
1. 梳理概述
在開始閱讀文章前妈踊,希望大家能認(rèn)真思考幾個(gè)問題:
- 界面卡頓的原理是怎樣的?
- ViewRootImpl 與 SurfaceFlinger 是怎么通信的?
- invalidate / requestLayout 會(huì)不會(huì)立馬刷新屏幕?
- SurfaceView / GLSurfaceView 的底層實(shí)現(xiàn)原理?
搞 Android 搞了幾年她渴,我們對 VSync 信號(hào)應(yīng)該會(huì)有一些了解,但是未必真正能理解其具體原理。比如 VSync 信號(hào)是從哪里來的癣防?發(fā)到哪里去?有什么作用掌眠?本文主要講解發(fā)到哪里去蕾盯,至于從哪里來的大家可以看看之前的內(nèi)容。
2. 請求 VSync 信號(hào)
如果我們的界面需要發(fā)生變化蓝丙,一般都會(huì)來到 ViewRootImpl 的 requestLayout 方法级遭,有可能是手動(dòng)觸發(fā)的也有可能是被動(dòng)觸發(fā)的,在這個(gè)方法里面我們會(huì)主動(dòng)去請求接收 VSync 信號(hào)渺尘,當(dāng)下一次 VSync 信號(hào)的來的時(shí)候會(huì)主動(dòng)回掉回來挫鸽,然后才開始真正的繪制流程。
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
// 插入一條消息屏障
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// post 一個(gè) Callback
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
}
}
private void postCallbackDelayedInternal(int callbackType, Object action, Object token, long delayMillis) {
synchronized (mLock) {
...
if (dueTime <= now) {
scheduleFrameLocked(now);
} else {
...
}
}
}
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
if (USE_VSYNC) {
// 是否在 Choreographer 的工作線程
if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
...
}
}
}
// 請求接收下一次 VSync 信號(hào)
private void scheduleVsyncLocked() {
mDisplayEventReceiver.scheduleVsync();
}
由上面的源碼可以看出鸥跟,每一次調(diào)用 requestLayout 方法丢郊,都會(huì)主動(dòng)調(diào)用 scheduleVsync 方法來接收下一次的 VSync 信號(hào)。也就是說在下一次 VSync 信號(hào)來之前锌雀,就算連續(xù)調(diào)用 n 次的 requestLayout 方法蚂夕,也并不會(huì)觸發(fā)刷新繪制流程。
3. 接收 VSync 信號(hào)
應(yīng)用 App 請求了要接收下一次的 VSync 信號(hào)腋逆,那么 SurfaceFlinger 服務(wù)怎么把 VSync 信號(hào)婿牍,發(fā)給我們的應(yīng)用 App ?這個(gè)得從 DisplayEventReceiver 的初始化入手惩歉,涉及到跨進(jìn)程通信也涉及到 Native 層源碼等脂。
public DisplayEventReceiver(Looper looper) {
...
// nativeInit
mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue);
}
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj) {
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env, receiverWeak, messageQueue);
// 初始化方法
status_t status = receiver->initialize();
receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
return reinterpret_cast<jlong>(receiver.get());
}
status_t NativeDisplayEventReceiver::initialize() {
// 接收端的 fd 添加到 Looper
int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,this, NULL);
return OK;
}
// 跨進(jìn)程創(chuàng)建一個(gè) mEventConnection 對象
DisplayEventReceiver::DisplayEventReceiver() {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != NULL) {
mEventConnection = sf->createDisplayEventConnection();
if (mEventConnection != NULL) {
mDataChannel = mEventConnection->getDataChannel();
}
}
}
// 獲取接收端的 fd
int DisplayEventReceiver::getFd() const {
if (mDataChannel == NULL)
return NO_INIT;
return mDataChannel->getFd();
}
// VSync 信號(hào)來會(huì)回調(diào)到這個(gè)方法
int NativeDisplayEventReceiver::handleEvent(int receiveFd, int events, void* data) {
// Drain all pending events, keep the last vsync.
nsecs_t vsyncTimestamp;
int32_t vsyncDisplayId;
uint32_t vsyncCount;
if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
mWaitingForVsync = false;
dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
}
return 1; // keep the callback
}
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
if (receiverObj.get()) {
// 回掉到 Java 層的 dispatchVsync 方法
env->CallVoidMethod(receiverObj.get(),
gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, id, count);
}
}
@Override
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
// 發(fā)消息執(zhí)行 doFrame 方法,真正開始刷新繪制流程
mTimestampNanos = timestampNanos;
mFrame = frame;
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
DisplayEventReceiver 在初始化時(shí)會(huì)創(chuàng)建與 SurfaceFlinger 的 Connection 連接撑蚌,當(dāng)應(yīng)用 App 主動(dòng)發(fā)起 requestNextVsync 后上遥,SurfaceFlinger 會(huì)在下一個(gè) VSync 信號(hào)來的時(shí)候,主動(dòng)通知我們的應(yīng)用 App 争涌,回掉到 Java 層的 onVsync 方法粉楚,開始真正的刷新繪制流程。
視頻地址:https://pan.baidu.com/s/1tQ7omRNg8BgldnkjdlBPlw
視頻密碼:6hlc