VSync是垂直同步(Vertical Synchronization)的简称。基本的思路是将设备的FPS和显示屏同步起来。其目的是避免显示出现"撕裂"现象,此文章主要是在android 10的代码上追下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的产生还是会受硬件控制的.
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发送数据)
(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)
(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)中的图用来作为总结: