Android为了提供一个稳固的帧率输出机制,让软件层和硬件层可以以共同的频率一起工作,引入了 Vsync + TripleBuffer + Choreographer 的刷帧机制。
引入Choreographer
Choreographer 的引入,重要是共同 Vsync ,给上层 App 的渲染提供一个稳固的 Message 处置处罚的时机,也就是 Vsync 到来的时间 ,会唤醒Choreographer 来做 App 的绘制利用。
Choreographer作用
Choreographer 扮演 Android 渲染链路中承上启下的脚色。
承上:负责接收和处置处罚 App 的各种更新消息和回调,比及 Vsync 到来的时间同一处置处罚。比如会合处置处罚 Input(重要是 Input 事故的处置处罚) 、Animation(动画相干)、Traversal(包括 measure、layout、draw 等利用) ,判断卡顿掉帧环境,纪录 CallBack 耗时等
启下:负责哀求和接收 Vsync 信号,通过申请和接收vsync来驱动app刷新。
简朴明白,Choreographer + SurfaceFlinger + Vsync + TripleBuffer这一套从上到下的机制,包管了 Android App 可以以一个稳固的帧率运行,减少帧率颠簸带来的不适感。下面从源码一探究竟Choreographer 的工作逻辑。
Choreographer初始化
文件:frameworks/base/core/java/android/view/ViewRootImpl.javapublic ViewRootImpl(Context context, Display display, IWindowSession session, boolean useSfChoreographer) { ... // ViewRootImpl 初始化的时间创建Choreographer mChoreographer = useSfChoreographer ? Choreographer.getSfInstance() : Choreographer.getInstance(); ...}文件:frameworks/base/core/java/android/view/Choreographer.java// Thread local storage for the choreographer. private static final ThreadLocal<Choreographer> sThreadInstance = new ThreadLocal<Choreographer>() { @Override protected Choreographer initialValue() { // 获取当火线程的looper Looper looper = Looper.myLooper(); if (looper == null) { throw new IllegalStateException("The current thread must have a looper!"); } // 创建Choreographer 对象,source范例为app Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP); if (looper == Looper.getMainLooper()) { mMainInstance = choreographer; } return choreographer; } }; private Choreographer(Looper looper, int vsyncSource) { mLooper = looper; // 初始化 FrameHandler mHandler = new FrameHandler(looper); // 初始化 DisplayEventReceiver mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper, vsyncSource) : null; mLastFrameTimeNanos = Long.MIN_VALUE; mFrameIntervalNanos = (long)(1000000000 / getRefreshRate()); // 初始化 CallbacksQueues,存放5种范例的callback mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1]; for (int i = 0; i <= CALLBACK_LAST; i++) { mCallbackQueues = new CallbackQueue(); } // b/68769804: For low FPS experiments. setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1)); } // 实现handleMessage 方法 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); break; case MSG_DO_SCHEDULE_VSYNC: doScheduleVsync(); break; case MSG_DO_SCHEDULE_CALLBACK: doScheduleCallback(msg.arg1); break; } } }我们把FrameDisplayEventReceiver 的初始化单独拿出来分析。
FrameDisplayEventReceiver初始化
文件:frameworks/base/core/java/android/view/Choreographer.java private final class FrameDisplayEventReceiver extends DisplayEventReceiver implements Runnable { private boolean mHavePendingVsync; private long mTimestampNanos; private int mFrame; public FrameDisplayEventReceiver(Looper looper, int vsyncSource) { // 实行DisplayEventReceiver 的初始化 super(looper, vsyncSource, CONFIG_CHANGED_EVENT_SUPPRESS); }文件:frameworks/base/core/java/android/view/DisplayEventReceiver.java public DisplayEventReceiver(Looper looper, int vsyncSource, int configChanged) { if (looper == null) { throw new IllegalArgumentException("looper must not be null"); } mMessageQueue = looper.getQueue(); // 通过jni调到native层 mReceiverPtr = nativeInit(new WeakReference<DisplayEventReceiver>(this), mMessageQueue, vsyncSource, configChanged); mCloseGuard.open("dispose"); }文件:frameworks/base/core/jni/android_view_DisplayEventReceiver.cppstatic jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj, jint vsyncSource, jint configChanged) { ... // NativeDisplayEventReceiver 继承 DisplayEventDispatcher, 实行DisplayEventDispatcher的初始化 sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env, receiverWeak, messageQueue, vsyncSource, configChanged); // 实行DisplayEventDispatcher::initialize status_t status = receiver->initialize(); ...}文件:frameworks/native/libs/gui/DisplayEventDispatcher.cppDisplayEventDispatcher:isplayEventDispatcher(const sp<Looper>& looper, ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) : mLooper(looper), mReceiver(vsyncSource, configChanged), mWaitingForVsync(false) { ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);}status_t DisplayEventDispatcher::initialize() { status_t result = mReceiver.initCheck(); if (result) { ALOGW("Failed to initialize display event receiver, status=%d", result); return result; } if (mLooper != nullptr) { // 添加mReceiveFd 监控,同Surfaceflinger的Message添加fd类似,区别是looper在差异的线程,回调的方法也不一样 int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL); if (rc < 0) { return UNKNOWN_ERROR; } } return OK;}这里告急的方法是mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL), 添加mReceiveFd 监控。那什么时间唤醒底层的loop等候呢?就是实行EventThread:: dispatchEvent,会对mSendFd进行write利用,这里接纳socket通讯,当监听到mReceiveFd 有变瞎搅时,进行唤醒,从而实行回调函数handleEvent。
文件:system/core/libutils/Looper.cppint Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {... Request request; request.fd = fd; request.ident = ident; request.events = events; request.seq = mNextRequestSeq++; request.callback = callback; request.data = data;... if (requestIndex < 0) { // 添加mReceiveFd 进行监控 int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &eventItem); if (epollResult < 0) { ALOGE("Error adding epoll events for fd %d: %s", fd, strerror(errno)); return -1; } mRequests.add(fd, request);...}int Looper::pollInner(int timeoutMillis) {...int eventCount = epoll_wait(mEpollFd.get(), eventItems, EPOLL_MAX_EVENTS, timeoutMillis);...for (size_t i = 0; i < mResponses.size(); i++) { ... // 实行addFd 时参加的回调函数 int callbackResult = response.request.callback->handleEvent(fd, events, data); ... return result;}文件:frameworks/native/libs/gui/DisplayEventDispatcher.cpp int DisplayEventDispatcher::handleEvent(int, int events, void*) { if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) { ALOGE("Display event receiver pipe was closed or an error occurred. " "events=0x%x", events); return 0; // remove the callback } if (!(events & Looper::EVENT_INPUT)) { ALOGW("Received spurious callback for unhandled poll event. " "events=0x%x", events); return 1; // keep the callback } // Drain all pending events, keep the last vsync. nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) { ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", count=%d", this, ns2ms(vsyncTimestamp), vsyncDisplayId, vsyncCount); mWaitingForVsync = false; dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount); } return 1; // keep the callback}到这里初始化完成,总结下做了哪些变乱:
- 初始化DisplayEventDispatcher,添加mReceiveFd进行监控,为vsync事故到来做回调预备
- 初始化CallbacksQueues,内里存放5种范例的callback
- 初始化FrameHandler,实现了handleMessage 方法
APP哀求Vsync
随着代码流程走到requestLayout(addView->setView->requestLayout->schduleTraversals)表现app要哀求vsync刷帧,具体看下哀求颠末
文件:frameworks/base/core/java/android/view/ViewRootImpl.java void scheduleTraversals() { if (!mTraversalScheduled) { mTraversalScheduled = true; mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); // 添加CALLBACK_TRAVERSAL 范例的回调 mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); notifyRendererOfFramePending(); pokeDrawLockIfNeeded(); } }文件: frameworks/base/core/java/android/view/Choreographer.java private void postCallbackDelayedInternal(int callbackType, Object action, Object token, long delayMillis) { if (DEBUG_FRAMES) { Log.d(TAG, "ostCallback: type=" + callbackType + ", action=" + action + ", token=" + token + ", delayMillis=" + delayMillis); } synchronized (mLock) { final long now = SystemClock.uptimeMillis(); final long dueTime = now + delayMillis; // mCallbackQueues[CALLBACK_TRAVERSAL] 队列添加一个回调 mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token); if (dueTime <= now) { // dueTime == now ,从这里进来 scheduleFrameLocked(now); } else { Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action); msg.arg1 = callbackType; msg.setAsynchronous(true); mHandler.sendMessageAtTime(msg, dueTime); } } }// CallbackRecord 是个单链表,有3个成员,dueTime,action,token和1个next指针// 将回调参加到当前的链表中public void addCallbackLocked(long dueTime, Object action, Object token) { CallbackRecord callback = obtainCallbackLocked(dueTime, action, token); CallbackRecord entry = mHead; if (entry == null) { mHead = callback; return; } if (dueTime < entry.dueTime) { callback.next = entry; mHead = callback; return; } while (entry.next != null) { if (dueTime < entry.next.dueTime) { callback.next = entry.next; break; } entry = entry.next; } entry.next = callback; }// obtainCallbackLocked 的作用是假如当前pool内里没有回调,则新创建一个,假如有,则返回当前的回调并将mCallbackPool 指向下一个回调private CallbackRecord obtainCallbackLocked(long dueTime, Object action, Object token) { CallbackRecord callback = mCallbackPool; if (callback == null) { callback = new CallbackRecord(); } else { mCallbackPool = callback.next; callback.next = null; } callback.dueTime = dueTime; callback.action = action; callback.token = token; return callback; } private void scheduleFrameLocked(long now) { if (!mFrameScheduled) { mFrameScheduled = true; if (USE_VSYNC) { if (DEBUG_FRAMES) { Log.d(TAG, "Scheduling next frame on vsync."); } // 判断looper是不是在主线程,这两个方法殊途同归,都会实行scheduleVsyncLocked if (isRunningOnLooperThreadLocked()) { scheduleVsyncLocked(); } else { Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC); msg.setAsynchronous(true); mHandler.sendMessageAtFrontOfQueue(msg); } ... } }private void scheduleVsyncLocked() { mDisplayEventReceiver.scheduleVsync(); }文件:frameworks/native/libs/gui/DisplayEventDispatcher.cppstatus_t DisplayEventDispatcher::scheduleVsync() { if (!mWaitingForVsync) { ... status_t status = mReceiver.requestNextVsync(); if (status) { ALOGW("Failed to request next vsync, status=%d", status); return status; } mWaitingForVsync = true; } return OK;}文件:frameworks/native/libs/gui/DisplayEventReceiver.cpp status_t DisplayEventReceiver::requestNextVsync() { if (mEventConnection != nullptr) { mEventConnection->requestNextVsync(); return NO_ERROR; } return NO_INIT;}文件:frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp void EventThreadConnection::requestNextVsync() { ATRACE_NAME("requestNextVsync"); mEventThread->requestNextVsync(this);}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(); }}跟着代码流程可以看到,终极调到app EventThread的requestNextVsync,将connection->vsyncRequest更新为Single,并唤醒mCondition的wait,用一副图表现。
APP接收Vsync
sw-vsync分发必要具备两个条件:1. 有哀求vsync的动作 2. TimerDispatch线程定时时间到,会make一个vsync event。在当前帧哀求vsync,在下一帧创造vsync event后就会回调给app。
文件:frameworks/native/services/surfaceflinger/Scheduler/EventThread.cppvoid EventThread::threadMain(std::unique_lock<std::mutex>& lock) {DisplayEventConsumers consumers; while (mState != State:uit) { std:ptional<DisplayEventReceiver::Event> event; // Determine next event to dispatch. if (!mPendingEvents.empty()) { event = mPendingEvents.front(); mPendingEvents.pop_front(); ... if (!consumers.empty()) { // 开始分发vsync event,假如是app eventthread就分发给app dispatchEvent(*event, consumers); consumers.clear(); }...}tatus_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) { ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1); return size < 0 ? status_t(size) : status_t(NO_ERROR);}文件:frameworks/native/libs/gui/DisplayEventReceiver.cppssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel, Event const* events, size_t count){ return gui::BitTube::sendObjects(dataChannel, events, count);}文件:frameworks/native/libs/gui/BitTube.cppssize_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); // should never happen because of SOCK_SEQPACKET LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)), "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were " "sent!)", count, objSize, size); // ALOGE_IF(size<0, "error %d sending %d events", size, count); return size < 0 ? size : size / static_cast<ssize_t>(objSize);}ssize_t BitTube::write(void const* vaddr, size_t size) { ssize_t err, len; do { // 对端mReceiveFd,会唤醒epoll_wait 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;}对端mReceiveFd 被添加到epllo fd进行监听,当变瞎搅暂时就会实行回调函数handleEvent
文件:frameworks/native/libs/gui/DisplayEventDispatcher.cppint DisplayEventDispatcher::handleEvent(int, int events, void*) { ... nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; // 得到发送过来的vsync event if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) { ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", count=%d", this, ns2ms(vsyncTimestamp), vsyncDisplayId, vsyncCount); mWaitingForVsync = false; // 处置处罚vsync event dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount); } return 1; // keep the callback}bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount) { bool gotVsync = false; DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE]; ssize_t n; // 获取发送过来的vsync event while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) { ALOGV("dispatcher %p ~ Read %d events.", this, int(n)); for (ssize_t i = 0; i < n; i++) { const DisplayEventReceiver::Event& ev = buf; switch (ev.header.type) { case DisplayEventReceiver:ISPLAY_EVENT_VSYNC: // Later vsync events will just overwrite the info from earlier // ones. That's fine, we only care about the most recent. gotVsync = true; *outTimestamp = ev.header.timestamp; *outDisplayId = ev.header.displayId; *outCount = ev.vsync.count; break; ... return gotVsync;}文件:frameworks/base/core/jni/android_view_DisplayEventReceiver.cppvoid NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) { JNIEnv* env = AndroidRuntime::getJNIEnv(); ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal)); if (receiverObj.get()) { ALOGV("receiver %p ~ Invoking vsync handler.", this); // 从jni调到java方法 env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, displayId, count); ALOGV("receiver %p ~ Returned from vsync handler.", this); } mMessageQueue->raiseAndClearException(env, "dispatchVsync");}文件:frameworks/base/core/java/android/view/DisplayEventReceiver.java private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame) { onVsync(timestampNanos, physicalDisplayId, frame); }文件:frameworks/base/core/java/android/view/Choreographer.javapublic void onVsync(long timestampNanos, long physicalDisplayId, int frame) { ... mTimestampNanos = timestampNanos; mFrame = frame; // obtain 会new message,callback为FrameDisplayEventReceiver对象,实现了Runnable的方法 Message msg = Message.obtain(mHandler, this); msg.setAsynchronous(true); // 发送message,唤醒loop wait mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS); }文件:frameworks/base/core/java/android/os/Message.java public static Message obtain(Handler h, Runnable callback) { Message m = obtain(); m.target = h; m.callback = callback; return m; }文件:frameworks/base/core/java/android/os/Handler.java public void dispatchMessage(@NonNull Message msg) { if (msg.callback != null) { // callback 不为空,走handleCallback handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } private static void handleCallback(Message message) { // 实行FrameDisplayEventReceiver的run方法 message.callback.run(); }文件:frameworks/base/core/java/android/view/Choreographer.java public void run() { mHavePendingVsync = false; // 处置处罚 App 的各种更新消息和回调 doFrame(mTimestampNanos, mFrame); } }从链路来看,末了会调到doFrame来处置处罚 App 的各种更新消息和回调,用个图总结下。
APP处置处罚Vsync
app接收到vsync信号后,就开始实行各种更新消息和回调,重要的处置处罚逻辑在doFrame函数。
文件:frameworks/base/core/java/android/view/Choreographer.javavoid doFrame(long frameTimeNanos, int frame) { // 处置处罚掉帧逻辑,临时不看 ... try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame"); AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS); // 纪录input开始时间 mFrameInfo.markInputHandlingStart(); // 回调input方法 doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos); //纪录动画开始时间 mFrameInfo.markAnimationsStart(); //回变动画方法 doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos); doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos); // 纪录Traversal开始时间 mFrameInfo.markPerformTraversalsStart(); // 回调Traversal 方法,重点看下 doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos); doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos); } finally { AnimationUtils.unlockAnimationClock(); Trace.traceEnd(Trace.TRACE_TAG_VIEW); } if (DEBUG_FRAMES) { final long endNanos = System.nanoTime(); Log.d(TAG, "Frame " + frame + ": Finished, took " + (endNanos - startNanos) * 0.000001f + " ms, latency " + (startNanos - frameTimeNanos) * 0.000001f + " ms."); } } void doCallbacks(int callbackType, long frameTimeNanos) { ... //取出对应的callback,还记得前面是通过addCallbackLocked将callback参加到链表内里,现将对应的callback取出 callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked( now / TimeUtils.NANOS_PER_MS); if (callbacks == null) { return; } mCallbacksRunning = true; ... try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]); for (CallbackRecord c = callbacks; c != null; c = c.next) { if (DEBUG_FRAMES) { Log.d(TAG, "RunCallback: type=" + callbackType + ", action=" + c.action + ", token=" + c.token + ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime)); } // 实行CallbackRecord的run方法 c.run(frameTimeNanos); } ... Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } private static final class CallbackRecord { public CallbackRecord next; public long dueTime; public Object action; // Runnable or FrameCallback public Object token; @UnsupportedAppUsage public void run(long frameTimeNanos) { if (token == FRAME_CALLBACK_TOKEN) { ((FrameCallback)action).doFrame(frameTimeNanos); } else { // 实行mTraversalRunnable的run方法,在scheduleTraversals内里通过postCallback参加callback链表 ((Runnable)action).run(); } } }文件:frameworks/base/core/java/android/view/ViewRootImpl.java final class TraversalRunnable implements Runnable { @Override public void run() { //末了回调到这个方法,处置处罚measure、layout、draw doTraversal(); } } private void performTraversals() {... performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);... performLayout(lp, mWidth, mHeight);... performDraw();...}可以看到当app接收到vsync信号后就开始处置处罚各种回调的方法,由于有些内容并不是很熟悉,也就没能继承分析下去,文章只是分析了大致的流程,具体的细节碰到题目再分析。
文章从app哀求vsync,eventThread分发vsync,再到app处置处罚vsync,分析了大致的流程,也印证了文章开始说的Choreographer作用: 1. 负责哀求和接收 Vsync 信号 2. 负责接收和处置处罚 App 的各种更新消息和回调,比及 Vsync 到来的时间同一处置处罚。 |