android Q 显示系统(一) VSync
VSync是垂直同步(Vertical Synchronization)的简称。基本的思路是将设备的FPS和显示屏同步起来。其目的是避免显示出现"撕裂"现象,此文章主要是在android 10的代码上追下VSync的主要流程,以后用来自己复习总结,有错误还请指出.
(1)VSync注册(接收HW_VSync)
SurfaceFlinger.h 继承自ComposerCallback
class SurfaceFlinger : private HWC2::ComposerCallback() /* ------------------------------------------------------------------------ * HWC2::ComposerCallback / HWComposer::EventHandler interface */ void onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, int64_t timestamp) override; void onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, HWC2::Connection connection) override; void onRefreshReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId) override;
HWC2.h ComposerCallback定义
class ComposerCallback { public: virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display, Connection connection) = 0; virtual void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) = 0; virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display, int64_t timestamp) = 0; virtual ~ComposerCallback() = default;};
HWC2.cpp 实现Hwc2::IComposerCallback(
ComposerHal.h --> namespace android{ namespace Hwc2 {
namespace V2_1 = hardware::graphics::composer::V2_1;
using V2_1::IComposerCallback;
}})
class ComposerCallbackBridge : public Hwc2::IComposerCallback {public: ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId) : mCallback(callback), mSequenceId(sequenceId) {} Return onHotplug(Hwc2::Display display, IComposerCallback::Connection conn) override { HWC2::Connection connection = static_cast(conn); mCallback->onHotplugReceived(mSequenceId, display, connection); return Void(); } Return onRefresh(Hwc2::Display display) override { mCallback->onRefreshReceived(mSequenceId, display); return Void(); } Return onVsync(Hwc2::Display display, int64_t timestamp) override { mCallback->onVsyncReceived(mSequenceId, display, timestamp); return Void(); }private: ComposerCallback* mCallback; int32_t mSequenceId;};
以上是将用于VSync注册的关键class,下面是真正的注册过程:
SurfaceFlinger.cpp 在init中注册HWComposer的回调
// Do not call property_set on main thread which will be blocked by init// Use StartPropertySetThread instead.void SurfaceFlinger::init() { /**/ mCompositionEngine->getHwComposer().registerCallback(this, getBE().mComposerSequenceId); // Process any initial hotplug and resulting display changes. /**/}
HWComposer.cpp 注册HWC2::Device的回调
void HWComposer::registerCallback(HWC2::ComposerCallback* callback, int32_t sequenceId) { mHwcDevice->registerCallback(callback, sequenceId);}
HWC2.cpp 实例化ComposerCallbackBridge注册android::Hwc2::Composer的回调
void Device::registerCallback(ComposerCallback* callback, int32_t sequenceId) { if (mRegisteredCallback) { ALOGW("Callback already registered. Ignored extra registration " "attempt."); return; } mRegisteredCallback = true; sp callbackBridge( new ComposerCallbackBridge(callback, sequenceId)); mComposer->registerCallback(callbackBridge);}
ComposerHal.cpp 注册hardware::graphics::composer::V2_1::IComposerClient的回调
void Composer::registerCallback(const sp& callback){ auto ret = mClient->registerCallback(callback); if (!ret.isOk()) { ALOGE("failed to register IComposerCallback"); }}
以上为VSync的注册全过程,可以看到VSync的产生还是会受硬件控制的.
(2)VSync 从HIDL到SurfaceFlinger的分发(HW_VSync到SW_VSync)
hardware::graphics::composer::V2_1::IComposerClient.h 开始分发给Hwc2::IComposerCallback
class HalEventCallback : public Hal::EventCallback { public: HalEventCallback(const sp callback, ComposerResources* resources) : mCallback(callback), mResources(resources) {} /**/ void onVsync(Display display, int64_t timestamp) { auto ret = mCallback->onVsync(display, timestamp); ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str()); } /**/ };
HWC2.cpp 分发给class SurfaceFlinger : private HWC2::ComposerCallback
class ComposerCallbackBridge : public Hwc2::IComposerCallback {public: ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId) : mCallback(callback), mSequenceId(sequenceId) {} /**/ Return onVsync(Hwc2::Display display, int64_t timestamp) override { mCallback->onVsyncReceived(mSequenceId, display, timestamp); return Void(); } /**/};
SurfaceFlinger.cpp开始分发
void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, int64_t timestamp) { ATRACE_NAME("SF onVsync"); Mutex::Autolock lock(mStateLock); // Ignore any vsyncs from a previous hardware composer. if (sequenceId != getBE().mComposerSequenceId) { return; } if (!getHwComposer().onVsync(hwcDisplayId, timestamp)) { return; } if (hwcDisplayId != getHwComposer().getInternalHwcDisplayId()) { // For now, we don't do anything with external display vsyncs. return; } bool periodChanged = false; mScheduler->addResyncSample(timestamp, &periodChanged); if (periodChanged) { mVsyncModulator.onRefreshRateChangeDetected(); }}
Scheduler.cpp 将VSync传递给DispSync。如果DipSync检测到vsync周期已更改,periodChange将为true,否则为false。
void Scheduler::addResyncSample(const nsecs_t timestamp, bool* periodChanged) { bool needsHwVsync = false; *periodChanged = false; { // Scope for the lock std::lock_guard lock(mHWVsyncLock); if (mPrimaryHWVsyncEnabled) { needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp, periodChanged); } } if (needsHwVsync) { enableHardwareVsync(); } else { disableHardwareVsync(false); }}
DispSync.cpp 往SW VSync模型中添加硬件VSync时间戳样本,同时在利用已经存在硬件vsync时间戳的实时更新下一次SW VSync的时间.此文章更详细:https://blog.csdn.net/zhuawalibai/article/details/87976799
bool DispSync::addResyncSample(nsecs_t timestamp, bool* periodChanged) { Mutex::Autolock lock(mMutex); ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp)); *periodChanged = false; const size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES; mResyncSamples[idx] = timestamp; if (mNumResyncSamples == 0) { mPhase = 0; ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, " "mReferenceTime = %" PRId64, mName, ns2us(mPeriod), ns2us(timestamp)); } else if (mPendingPeriod > 0) { // mNumResyncSamples > 0, so priorIdx won't overflow const size_t priorIdx = (mFirstResyncSample + mNumResyncSamples - 1) % MAX_RESYNC_SAMPLES; const nsecs_t lastTimestamp = mResyncSamples[priorIdx]; const nsecs_t observedVsync = std::abs(timestamp - lastTimestamp); if (std::abs(observedVsync - mPendingPeriod) < std::abs(observedVsync - mPeriod)) { // Observed vsync is closer to the pending period, so reset the // model and flush the pending period. resetLocked(); mPeriod = mPendingPeriod; mPendingPeriod = 0; if (mTraceDetailedInfo) { ATRACE_INT("DispSync:PendingPeriod", mPendingPeriod); } *periodChanged = true; } } // Always update the reference time with the most recent timestamp. mReferenceTime = timestamp; mThread->updateModel(mPeriod, mPhase, mReferenceTime); if (mNumResyncSamples < MAX_RESYNC_SAMPLES) { mNumResyncSamples++; } else { mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES; } updateModelLocked(); if (mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) { resetErrorLocked(); } if (mIgnorePresentFences) { // If we're ignoring the present fences we have no way to know whether // or not we're synchronized with the HW vsyncs, so we just request // that the HW vsync events be turned on. return true; } // Check against kErrorThreshold / 2 to add some hysteresis before having to // resync again bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2) && mPendingPeriod == 0; ALOGV("[%s] addResyncSample returning %s", mName, modelLocked ? "locked" : "unlocked"); if (modelLocked) { mThread->lockModel(); } return !modelLocked;}
DispSync.cpp fireCallbackInvocations函数遍历回调列表调用其onDispSyncEvent函数。
void fireCallbackInvocations(const std::vector& callbacks) { if (mTraceDetailedInfo) ATRACE_CALL(); for (size_t i = 0; i < callbacks.size(); i++) { callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime); } }
DispSyncSource.h (DispSyncSource final : public VSyncSource, private DispSync::Callback)
DispSyncSource.cpp 实现 DispSync::Callback ,在自身onDispSyncEvent函数中处理VSync信号
void DispSyncSource::onDispSyncEvent(nsecs_t when) { VSyncSource::Callback* callback; { std::lock_guard lock(mCallbackMutex); callback = mCallback; if (mTraceVsync) { mValue = (mValue + 1) % 2; ATRACE_INT(mVsyncEventLabel.c_str(), mValue); } } if (callback != nullptr) { callback->onVSyncEvent(when); }}
EventThread.h (class EventThread : public android::EventThread, private VSyncSource::Callback)
EventThread.cpp 实现 DispSync::Callback,在自身onVSyncEvent去创建Event事件
void EventThread::onVSyncEvent(nsecs_t timestamp) { std::lock_guard lock(mMutex); LOG_FATAL_IF(!mVSyncState); mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count)); mCondition.notify_all();}DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp, uint32_t count) { DisplayEventReceiver::Event event; event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp}; event.vsync.count = count; return event;}
EventThread.cpp threadMain循环处理Event事件
void EventThread::threadMain(std::unique_lock& lock) { DisplayEventConsumers consumers; while (mState != State::Quit) { std::optional event; // Determine next event to dispatch. if (!mPendingEvents.empty()) { event = mPendingEvents.front(); mPendingEvents.pop_front(); switch (event->header.type) { case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: if (event->hotplug.connected && !mVSyncState) { mVSyncState.emplace(event->header.displayId); } else if (!event->hotplug.connected && mVSyncState && mVSyncState->displayId == event->header.displayId) { mVSyncState.reset(); } break; case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: if (mInterceptVSyncsCallback) { mInterceptVSyncsCallback(event->header.timestamp); } break; } } bool vsyncRequested = false; // Find connections that should consume this event. auto it = mDisplayEventConnections.begin(); while (it != mDisplayEventConnections.end()) { if (const auto connection = it->promote()) { vsyncRequested |= connection->vsyncRequest != VSyncRequest::None; if (event && shouldConsumeEvent(*event, connection)) { consumers.push_back(connection); } ++it; } else { it = mDisplayEventConnections.erase(it); } } if (!consumers.empty()) { dispatchEvent(*event, consumers); consumers.clear(); } State nextState; if (mVSyncState && vsyncRequested) { nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync; } else { ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected"); nextState = State::Idle; } if (mState != nextState) { if (mState == State::VSync) { mVSyncSource->setVSyncEnabled(false); } else if (nextState == State::VSync) { mVSyncSource->setVSyncEnabled(true); } mState = nextState; } if (event) { continue; } // Wait for event or client registration/request. if (mState == State::Idle) { mCondition.wait(lock); } else { // Generate a fake VSYNC after a long timeout in case the driver stalls. When the // display is off, keep feeding clients at 60 Hz. const auto timeout = mState == State::SyntheticVSync ? 16ms : 1000ms; if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) { ALOGW_IF(mState == State::VSync, "Faking VSYNC due to driver stall"); LOG_FATAL_IF(!mVSyncState); mPendingEvents.push_back(makeVSync(mVSyncState->displayId, systemTime(SYSTEM_TIME_MONOTONIC), ++mVSyncState->count)); } } }}
EventThread.cpp dispatchEvent 分发事件给EventThreadConnection
void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event, const DisplayEventConsumers& consumers) { for (const auto& consumer : consumers) { switch (consumer->postEvent(event)) { case NO_ERROR: break; case -EAGAIN: // TODO: Try again if pipe is full. ALOGW("Failed dispatching %s for %s", toString(event).c_str(), toString(*consumer).c_str()); break; default: // Treat EPIPE and other errors as fatal. removeDisplayEventConnectionLocked(consumer); } }}status_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);}
EventThread.cpp EventThreadConnection::postEvent分发事件
status_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);}
DisplayEventReceiver.cpp EventThreadConnection通过DisplayEventReceiver::sendEvents静态方法利用mChannel(gui::BitTube)去发送事件.
public: enum { DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'), DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'), DISPLAY_EVENT_CONFIG_CHANGED = fourcc('c', 'o', 'n', 'f'), }; struct Event { struct Header { uint32_t type; PhysicalDisplayId displayId; nsecs_t timestamp __attribute__((aligned(8))); }; struct VSync { uint32_t count; }; struct Hotplug { bool connected; }; struct Config { int32_t configId; }; Header header; union { VSync vsync; Hotplug hotplug; Config config; }; };ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel, Event const* events, size_t count){ return gui::BitTube::sendObjects(dataChannel, events, count);}
BitTube.cpp sendObjects 会利用内置的成对的socket发送事件.
// send objects (sized blobs). All objects are guaranteed to be written or the call fails. template static ssize_t sendObjects(BitTube* tube, T const* events, size_t count) { return sendObjects(tube, events, count, sizeof(T)); }ssize_t BitTube::sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize) { const char* vaddr = reinterpret_cast(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(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(objSize);}ssize_t BitTube::write(void const* vaddr, size_t size) { ssize_t err, len; do { 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;}
到此为止,SufaceFlinger之下的VSync分发过程就到此为止了,此前分析是从hidl开始到SufaceFlinger结束的,因为从SufaceFlinger到app的发送过程需要先分析些前提,所以此处暂做一个小结.
onVsync( hardware::graphics::composer::V2_1::IComposerClient.h)
--> onVsync(ComposerHal.h hardware::graphics::composer::V2_1::IComposerCallback)
--> onVsyncReceived(SurfaceFlinger.cpp class SurfaceFlinger : private HWC2::ComposerCallback)
--> addResyncSample(Scheduler.cpp)
--> addResyncSample(DispSync.cpp 利用硬件VSync时间戳样本实时更新SW VSync模型)
--> fireCallbackInvocations(DispSync.cpp)
--> onDispSyncEvent(DispSyncSource final : public VSyncSource, private DispSync::Callback)
--> onVSyncEvent(class EventThread : public android::EventThread, private VSyncSource::Callback)
--> mPendingEvents.push_back(makeVSync)(EventThread.cpp生成类型为DisplayEventReceiver::DISPLAY_EVENT_VSYNC的DisplayEventReceiver::Event)
threadMain(EventThread.cpp 循环读取DisplayEventReceiver::Event)
--> mPendingEvents.front()/threadMain (EventThread.cpp 通过threadMain提取DisplayEventReceiver::Event)
--> dispatchEvent(EventThread.cpp)
--> postEvent(EventThread.cpp)
-->static DisplayEventReceiver::sendEvents(DisplayEventReceiver.cpp)
--> gui::BitTube::sendObjects(BitTube.h)
--> sendObjects(BitTube.cpp)
--> write(BitTube.cpp 利用socket发送数据)
以下是app与SF分别接受VSync的追踪
(3)VSync 从SurfaceFlinger到SurfaceFlinger的分发(SF VSync)
(a)SurfaceFlinger自己对于VSync的注册过程为
SurfaceFlinger.cpp SurfaceFlinger会先生成std::unique_ptr
SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) : mFactory(factory), mPhaseOffsets(mFactory.createPhaseOffsets()), mInterceptor(mFactory.createSurfaceInterceptor(this)), mTimeStats(mFactory.createTimeStats()), mEventQueue(mFactory.createMessageQueue()), mCompositionEngine(mFactory.createCompositionEngine()) {}void SurfaceFlinger::onFirstRef(){ mEventQueue->init(this);}void SurfaceFlinger::init() { /* */ mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(), resyncCallback, [this](nsecs_t timestamp) { mInterceptor->saveVSyncEvent(timestamp); }); mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle)); /* */}
(b)SurfaceFlinger自己对于VSync的接收过程
MessageQueue.cpp MessageQueue的setEventConnection函数会利用EventThread中生成时预置的一个EventThreadConnection的stealReceiveChannel方法获取到EventThreadConnection的gui::BitTube,之后利用Handler传递给SurfaceFlinger
int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) { ssize_t n; DisplayEventReceiver::Event buffer[8]; while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) { for (int i = 0; i < n; i++) { if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { mHandler->dispatchInvalidate(); break; } } } return 1;}void MessageQueue::Handler::dispatchInvalidate() { if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) { mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE)); }}void MessageQueue::Handler::handleMessage(const Message& message) { switch (message.what) { case INVALIDATE: android_atomic_and(~eventMaskInvalidate, &mEventMask); mQueue.mFlinger->onMessageReceived(message.what); break; case REFRESH: android_atomic_and(~eventMaskRefresh, &mEventMask); mQueue.mFlinger->onMessageReceived(message.what); break; }}
SurfaceFlinger.cpp 会在onMessageReceived中处理接到Message事件.
void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); switch (what) { case MessageQueue::INVALIDATE: { bool frameMissed = previousFrameMissed(); bool hwcFrameMissed = mHadDeviceComposition && frameMissed; bool gpuFrameMissed = mHadClientComposition && frameMissed; ATRACE_INT("FrameMissed", static_cast(frameMissed)); ATRACE_INT("HwcFrameMissed", static_cast(hwcFrameMissed)); ATRACE_INT("GpuFrameMissed", static_cast(gpuFrameMissed)); if (frameMissed) { mFrameMissedCount++; mTimeStats->incrementMissedFrames(); } if (hwcFrameMissed) { mHwcFrameMissedCount++; } if (gpuFrameMissed) { mGpuFrameMissedCount++; } if (mUseSmart90ForVideo) { // This call is made each time SF wakes up and creates a new frame. It is part // of video detection feature. mScheduler->updateFpsBasedOnContent(); } if (performSetActiveConfig()) { break; } if (frameMissed && mPropagateBackpressure) { if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) { signalLayerUpdate(); break; } } // Now that we're going to make it to the handleMessageTransaction() // call below it's safe to call updateVrFlinger(), which will // potentially trigger a display handoff. updateVrFlinger(); bool refreshNeeded = handleMessageTransaction(); refreshNeeded |= handleMessageInvalidate(); updateCursorAsync(); updateInputFlinger(); refreshNeeded |= mRepaintEverything; if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) { // Signal a refresh if a transaction modified the window state, // a new buffer was latched, or if HWC has requested a full // repaint signalRefresh(); } break; } case MessageQueue::REFRESH: { handleMessageRefresh(); break; } }}
SF VSync分发小结
eventReceiver (MessageQueue.cpp)
-->dispatchInvalidate(MessageQueue.cpp)
-->handleMessage(MessageQueue.cpp)
-->onMessageReceived(SurfaceFlinger.cpp)
(4)VSync 从SurfaceFlinger到app的分发
(a)app在SurfaceFlinger中对于VSync的注册过程为:
SurfaceFlinger.cpp 其中在init()中生成专属app的ConnectionHandle,用于在Scheduler中找到自己.
void SurfaceFlinger::init() { /* */ mAppConnectionHandle = mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(), resyncCallback, impl::EventThread::InterceptVSyncsCallback()); /* */}
Scheduler.cpp 生成专属app的EventThread用于接收VSync
sp Scheduler::createConnection( const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback, impl::EventThread::InterceptVSyncsCallback interceptCallback) { const int64_t id = sNextId++; ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id); std::unique_ptr eventThread = makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs, std::move(interceptCallback)); auto eventThreadConnection = createConnectionInternal(eventThread.get(), std::move(resyncCallback)); mConnections.emplace(id, std::make_unique(new ConnectionHandle(id), eventThreadConnection, std::move(eventThread))); return mConnections[id]->handle;}std::unique_ptr Scheduler::makeEventThread( const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs, impl::EventThread::InterceptVSyncsCallback interceptCallback) { std::unique_ptr eventThreadSource = std::make_unique(dispSync, phaseOffsetNs, true, connectionName); return std::make_unique(std::move(eventThreadSource), std::move(interceptCallback), connectionName);}sp Scheduler::createConnectionInternal(EventThread* eventThread, ResyncCallback&& resyncCallback) { return eventThread->createEventConnection(std::move(resyncCallback));}
以上是在SurfaceFlinger中生成了专属app的EventThread并注册到DispSync中,此EventThread一边在循环读取着DispSync传来的VSync的事件,一边等待着应用通过SurfaceFlinger在自己中注册应用的VSync接受器IDisplayEventConnection,以下从java层开始记录此注册过程:
ViewRootImpl.java 在ViewRootImpl构造过程中,会生成一个Choreographer,Choreographer是用来协调动画、输入和绘图的时间的
public ViewRootImpl(Context context, Display display) { /* */ mChoreographer = Choreographer.getInstance(); /* */ }
Choreographer.java 中会获取当前线程的独立的一个Choreographer实例,在new Choreographer中会new一个FrameDisplayEventReceiver.
// Thread local storage for the choreographer. private static final ThreadLocal sThreadInstance = new ThreadLocal() { @Override protected Choreographer initialValue() { Looper looper = Looper.myLooper(); if (looper == null) { throw new IllegalStateException("The current thread must have a looper!"); } Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP); if (looper == Looper.getMainLooper()) { mMainInstance = choreographer; } return choreographer; } }; /** * Gets the choreographer for the calling thread. Must be called from * a thread that already has a {@link android.os.Looper} associated with it. * * @return The choreographer for this thread. * @throws IllegalStateException if the thread does not have a looper. */ public static Choreographer getInstance() { return sThreadInstance.get(); } private Choreographer(Looper looper, int vsyncSource) { mLooper = looper; mHandler = new FrameHandler(looper); mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper, vsyncSource) : null; mLastFrameTimeNanos = Long.MIN_VALUE; mFrameIntervalNanos = (long)(1000000000 / getRefreshRate()); mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1]; for (int i = 0; i <= CALLBACK_LAST; i++) { mCallbackQueues[i] = new CallbackQueue(); } // b/68769804: For low FPS experiments. setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1)); }
Choreographer.java FrameDisplayEventReceiver扩展至DisplayEventReceiver
private final class FrameDisplayEventReceiver extends DisplayEventReceiver implements Runnable { public FrameDisplayEventReceiver(Looper looper, int vsyncSource) { super(looper, vsyncSource); } }
DisplayEventReceiver.java 在其构造函数中会通过nativeInit把DisplayEventReceiver的弱引用传到Native层(方便后续通过反射回调),
/** * Creates a display event receiver. * * @param looper The looper to use when invoking callbacks. * @param vsyncSource The source of the vsync tick. Must be on of the VSYNC_SOURCE_* values. */ public DisplayEventReceiver(Looper looper, int vsyncSource) { if (looper == null) { throw new IllegalArgumentException("looper must not be null"); } mMessageQueue = looper.getQueue(); mReceiverPtr = nativeInit(new WeakReference(this), mMessageQueue, vsyncSource); mCloseGuard.open("dispose"); }
android_view_DisplayEventReceiver.cpp nativeInit函数中NativeDisplayEventReceiver会在new的过程中给予其父类DisplayEventDispatcher的属性赋值,并通过receiver->initialize()与SurfaceFlinger发生联系.
NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak, const sp& messageQueue, jint vsyncSource) : DisplayEventDispatcher(messageQueue->getLooper(), static_cast(vsyncSource)), mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)), mMessageQueue(messageQueue) { ALOGV("receiver %p ~ Initializing display event receiver.", this);}static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject messageQueueObj, jint vsyncSource) { sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); if (messageQueue == NULL) { jniThrowRuntimeException(env, "MessageQueue is not initialized."); return 0; } sp receiver = new NativeDisplayEventReceiver(env, receiverWeak, messageQueue, vsyncSource); status_t status = receiver->initialize(); if (status) { String8 message; message.appendFormat("Failed to initialize display event receiver. status=%d", status); jniThrowRuntimeException(env, message.string()); return 0; } receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object return reinterpret_cast(receiver.get());}
DisplayEventDispatcher.cpp 其属性mReceiver(DisplayEventReceiver)初始化,看到这个不陌生了把,DisplayEventReceiver的静态函数曾被SurfaceFlinger中调用过,用于BitTube的数据传递,此处在正好用到了它,另外在initialize()中,我们又看到了熟悉的mLooper->addFd,
DisplayEventDispatcher::DisplayEventDispatcher(const sp& looper, ISurfaceComposer::VsyncSource vsyncSource) : mLooper(looper), mReceiver(vsyncSource), 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; } int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, this, NULL); if (rc < 0) { return UNKNOWN_ERROR; } return OK;}
DisplayEventReceiver.cpp 此时是处于APP的Native运行中,那么是什么样的方法与SurfaceFlinger链接在一起的呢?
其实在BitTube创建之初,BitTube中已经生成了一对互相链接的socket,BitTube会记录这对socket的文件句柄(mReceiveFd,mSendFd),在DisplayEventReceiver的构造函数中利用IDisplayEventConnection的stealReceiveChannel方法,把此时的mReceiveFd替换为SurfaceFlinger中存在的一个BitTube的mReceiveFd,这样就形成了socket的跨线程通信.
DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) { sp sf(ComposerService::getComposerService()); if (sf != nullptr) { mEventConnection = sf->createDisplayEventConnection(vsyncSource); if (mEventConnection != nullptr) { mDataChannel = std::make_unique(); mEventConnection->stealReceiveChannel(mDataChannel.get()); } }}
*** 此处附上BitTube的跨线程通信原理:
app注册到SurfaceFlinger小结:
new ViewRootImpl(ViewRootImpl.java)
-->getInstance(Choreographer.java)
--> new Choreographer(Choreographer.java)
--> new FrameDisplayEventReceiver(Choreographer.java)
--> new DisplayEventReceiver(DisplayEventReceiver.java)
--> nativeInit(android_view_DisplayEventReceiver.cpp)
--> initialize(DisplayEventDispatcher.cpp)
--> new DisplayEventReceiver(DisplayEventReceiver.cpp)
--> stealReceiveChannel(DisplayEventReceiver.cpp)
(b)SurfaceFlinger分发VSync到app的过程:
DisplayEventDispatcher.cpp此实例中会在handleEvent中利用processPendingEvents读取VSync事件,并通过dispatchVsync传递出去
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}bool DisplayEventDispatcher::processPendingEvents( nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount) { bool gotVsync = false; DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE]; ssize_t n; 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[i]; switch (ev.header.type) { case DisplayEventReceiver::DISPLAY_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; case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected); break; case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: dispatchConfigChanged(ev.header.timestamp, ev.header.displayId, ev.config.configId); break; default: ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type); break; } } } if (n < 0) { ALOGW("Failed to get events from display event dispatcher, status=%d", status_t(n)); } return gotVsync;}
android_view_DisplayEventReceiver.cpp 此处class NativeDisplayEventReceiver : public DisplayEventDispatcher,并实现了其方法dispatchVsync,用于处理VSync.处理的方法是利用之前得到的java实例DisplayEventReceiver,反射使用其方法dispatchVsync
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) { JNIEnv* env = AndroidRuntime::getJNIEnv(); ScopedLocalRef receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal)); if (receiverObj.get()) { ALOGV("receiver %p ~ Invoking vsync handler.", this); env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, displayId, count); ALOGV("receiver %p ~ Returned from vsync handler.", this); } mMessageQueue->raiseAndClearException(env, "dispatchVsync");}
DisplayEventReceiver.java dispatchVsync方法中调用了onVsync方法,我们需要取器子类中找
// Called from native code. @SuppressWarnings("unused") @UnsupportedAppUsage private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame) { onVsync(timestampNanos, physicalDisplayId, frame); }
Choreographer.java DisplayEventReceiver的子类FrameDisplayEventReceiver重写了onVsync方法,其又利用Message.obtain(mHandler, this)的方法,使得其继承自Runnable的run()方法可以在指定的时间之后运行当前Choreographer的线程中.
@Override public void onVsync(long timestampNanos, long physicalDisplayId, int frame) { // Post the vsync event to the Handler. // The idea is to prevent incoming vsync events from completely starving // the message queue. If there are no messages in the queue with timestamps // earlier than the frame time, then the vsync event will be processed immediately. // Otherwise, messages that predate the vsync event will be handled first. long now = System.nanoTime(); if (timestampNanos > now) { Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f) + " ms in the future! Check that graphics HAL is generating vsync " + "timestamps using the correct timebase."); timestampNanos = now; } if (mHavePendingVsync) { Log.w(TAG, "Already have a pending vsync event. There should only be " + "one at a time."); } else { mHavePendingVsync = true; } mTimestampNanos = timestampNanos; mFrame = frame; Message msg = Message.obtain(mHandler, this); msg.setAsynchronous(true); mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS); }
Choreographer.java 在FrameDisplayEventReceiver的run()方法中开始进入doFrame操作
private final class FrameDisplayEventReceiver extends DisplayEventReceiver implements Runnable { @Override public void run() { mHavePendingVsync = false; doFrame(mTimestampNanos, mFrame); } }
分发VSync到app的过程小结:
handleEvent(DisplayEventDispatcher.cpp)
-->processPendingEvents(DisplayEventDispatcher.cpp)
-->dispatchVsync(android_view_DisplayEventReceiver.cpp)
-->dispatchVsync(DisplayEventReceiver.java 利用发射机制有native层调用)
-->onVsync(Choreographer.java)
-->sendMessageAtTime(Choreographer.java 指定时间运行run()方法)
-->run(Choreographer.java)
-->doFrame(Choreographer.java)
结尾出附上大神文章(https://www.jianshu.com/p/d3e4b1805c92)中的图用来作为总结:
更多相关文章
- Android Studio打包生成Jar包的方法(亲测可用)
- Android 中调试手段 打印函数调用栈信息
- Android 中broadcast 注册过程解析
- Android更新UI的方法
- Eclipse中编译Android工程时出现的问题解决方法。
- Android studio获取证书指纹 (SHA1)的方法
- Android 解析XML文件方法