android 图形学之图层数据送显及合成图层(七)

填充完成之后,调用Surface unlockAndPost进行刷图送显。

Surface::unlockAndPost的实现

cpp 复制代码
status_t Surface::unlockAndPost()
{
    status_t err = mLockedBuffer->unlockAsync(&fd);
 
    err = queueBuffer(mLockedBuffer.get(), fd);
 
    mPostedBuffer = mLockedBuffer;
    mLockedBuffer = nullptr;
    return err;
}

调用了queueBuffer的方法

cpp 复制代码
int Surface::queueBuffer(sp<GraphicBuffer>&& buffer, int fenceFd,SurfaceQueueBufferOutput* surfaceOutput//默认是nullptr) {
    IGraphicBufferProducer::QueueBufferOutput output;
    IGraphicBufferProducer::QueueBufferInput input;
    ........
    getQueueBufferInputLocked(buffer, fenceFd, mTimestamp, &input);
    sp<Fence> fence = input.fence;
     ........
    status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
 
    onBufferQueuedLocked(i, fence, output);
    return err;
}

调用了mGraphicBufferProducer生成者的入队列方法

cpp 复制代码
status_t BufferQueueProducer::queueBuffer(int slot,
        const QueueBufferInput &input, QueueBufferOutput *output) {
    BufferItem item;
    
        item.mAcquireCalled = mSlots[slot].mAcquireCalled;
        item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
        item.mCrop = crop;
        ... ...
            mCore->mQueue.push_back(item);
            frameAvailableListener = mCore->mConsumerListener;
 
        if (frameAvailableListener != nullptr) {
            frameAvailableListener->onFrameAvailable(item);
        } else if (frameReplacedListener != nullptr) {
            frameReplacedListener->onFrameReplaced(item);
        } 
}

重点是调用frameAvailableListener->onFrameAvailable(item);通知Listener当前有可用的buffer了。

cpp 复制代码
android::BufferQueueConsumer::acquireBuffer BufferQueueConsumer.cpp:85
android::ConsumerBase::acquireBufferLocked ConsumerBase.cpp:392
android::BufferItemConsumer::acquireBuffer BufferItemConsumer.cpp:66
//在这个方法的里面获取bufferItem之后,会进行事务的提交
//status_t status = t->setApplyToken(mApplyToken).apply(false, true)
android::BLASTBufferQueue::acquireNextBufferLocked BLASTBufferQueue.cpp:474
android::BLASTBufferQueue::onFrameAvailable BLASTBufferQueue.cpp:694
android::ConsumerBase::onFrameAvailable ConsumerBase.cpp:157
android::BufferQueue::ProxyConsumerListener::onFrameAvailable BufferQueue.cpp:71
android::BufferQueueProducer::queueBuffer BufferQueueProducer.cpp:1054
android::Surface::queueBuffer Surface.cpp:1190

事务提交之后,会经过binder的调用,调用到surfaceflinger的::setTransactionFlags函数

cpp 复制代码
 void SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule schedule,FrameHint frameHint,
 std::vector<gui::EarlyWakeupInfo> earlyWakeupInfos) {
        mScheduler->modulateVsync({}, &VsyncModulator::setTransactionSchedule, schedule,
                                std::move(earlyWakeupInfos));
      uint32_t transactionFlags = mTransactionFlags.fetch_or(mask);
      SFTRACE_INT("mTransactionFlags", transactionFlags);
  
      if (const bool scheduled = transactionFlags & mask; !scheduled) {
          if (FlagManager::getInstance().resync_on_tx() &&                  FlagManager::getInstance().vsync_predictor_predicts_within_threshold()) {
              mScheduler->resync(IEventThreadCallback::ResyncCaller::Transaction);
          }
          scheduleCommit(frameHint);
      } else if (frameHint == FrameHint::kActive) {
         // Even if the next frame is already scheduled, we should reset the idle timer
          // as a new activity just happened.
          mScheduler->resetAllIdleTimers();
      }
  }

scheduleCommit(frameHint)这个函数会触发任务的执行

cpp 复制代码
void SurfaceFlinger::scheduleCommit(FrameHint hint, Duration workDurationSlack) {
      if (hint == FrameHint::kActive) {
          mScheduler->resetAllIdleTimers();
      }
      mPowerAdvisor->notifyDisplayUpdateImminentAndCpuReset();
      mScheduler->scheduleFrame(workDurationSlack);
  }

注意 MessageQueue::scheduleFrame

Scheduler继承自MessageQueue,所以这里实际执行的是MessageQueue::scheduleFrame

mVsync.registration->schedule是不是看着很眼熟,2.3.1已经讲过这个逻辑了,最终他会回调VSyncCallbackRegistration内部的mCallback,我们往下来看看这里的mCallback是哪里传入的

cpp 复制代码
void MessageQueue::scheduleFrame() {
    ATRACE_CALL();

    std::lock_guard lock(mVsync.mutex);
    // 前面已经介绍过了,这里的逻辑和app请求是一样的。
    mVsync.scheduledFrameTime =
            mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                        .readyDuration = 0,
                                        .earliestVsync = mVsync.lastCallbackTime.ns()});
}
最终回调方法是MessageQueue::vsyncCallback,也可以直接跳到3.5章节。

sf的vsync也是由app层面进行queuebuffer后,通过夸进程setTransactionState方法调用到SurfaceFlinger端,SurfaceFlinger端会检测transation是否有相关的变化,有变化则触发申请vsync信号。

VSyncCallbackRegistration.schedule,这里是请求VSync信号的关键,实际上调用了mDispatch->schedule,这个mDispatch是从VsyncSchedule::createDispatch方法构造的,是一个VSyncDispatchTimerQueue对象,所以这里就是调用VSyncDispatchTimerQueue::schedule。

cpp 复制代码
  //下面是VSyncCallbackRegistration的schedule
ScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) {
    if (!mToken) {
        return std::nullopt;
    }
    // 调用了mDispatch::schedule,这里的mDispatch是在EventThread构造函数构造VSyncCallbackRegistration时候传入的
    // 最终可以看到mDispatch是一个VSyncDispatchTimerQueue,我们接下去看VSyncDispatchTimerQueue::schedule,详见2.3.2
    return mDispatch->schedule(*mToken, scheduleTiming);
}

EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule,
                        android::frametimeline::TokenManager* tokenManager,
                        ThrottleVsyncCallback throttleVsyncCallback,
                        GetVsyncPeriodFunction getVsyncPeriodFunction,
                        std::chrono::nanoseconds workDuration,
                        std::chrono::nanoseconds readyDuration)
    : mThreadName(name),
        mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0),
        mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
        mReadyDuration(readyDuration),
        mVsyncSchedule(std::move(vsyncSchedule)),
        // 可以看到mDispatch是从vsyncSchedule->getDispatch方法获取的
        // VsyncSchedule是软件VSync模拟的核心类,dispatch是通过VsyncSchedule::createDispatch方法构造的
        // 是一个VSyncDispatchTimerQueue对象,这里就不跟了,我们直接看VSyncDispatchTimerQueue::schedule,详见2.3.2
        mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), name),
        mTokenManager(tokenManager),
        mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
        mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) {
    // 。。。
}
复制代码
上面的调用关系都很简单,没啥业务,直到调用到了dispatch的schedule才是核心
cpp 复制代码
ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token, ScheduleTiming scheduleTiming) {
    ScheduleResult result;
    {
        //这里又会调用到callback的schedule,其实就另一个重载方法,这里会获取出具体的wakeupTime等,是核心部分
        result = callback->schedule(scheduleTiming, mTracker, now);
        //这里会判断上面计算的wakeupTime是否小于mIntendedWakeupTime,小于才需要重新定时,如果大于就不需要了,直接return
        if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) {
            rearmTimerSkippingUpdateFor(now, it);//启动定时任务相关
        }
    }

    return result;
}

来看看核心方法callback->schedule是怎么计算的这个wakeup等重要参数的:

cpp 复制代码
    ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
                                                          VSyncTracker& tracker, nsecs_t now) {
        //核心方法,给一个时间点,然后可以获取到这个时间点对于的硬件vsync,即上屏的vsync时间点就是nextVsyncTime
        auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
                std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
        //通过nextVsyncTime来获取唤醒时间部分
        auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
          //省略
        //上面计算出来的时间,然后包装到mArmedInfo中
        mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
        //返回时间点
        return getExpectedCallbackTime(nextVsyncTime, timing);
    }
    //其实是返回wakeuptime
    nsecs_t getExpectedCallbackTime(nsecs_t nextVsyncTime,
                                    const VSyncDispatch::ScheduleTiming& timing) {
        return nextVsyncTime - timing.readyDuration - timing.workDuration;
    }

核心方法是nextAnticipatedVSyncTimeFrom,这个方法很复杂,大家先把他当做个功能黑盒,后面会带大家详细分析。

https://blog.csdn.net/weixin_43833152/article/details/139940649

2.3.4 VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor

重置定时器,wakeupTime是schedule计算出来的时间,PendingWorkloadUpdate是之前存储的唤醒时间,如果都没有则说明这个callback当前没有人请求VSync,否则就会调用update重新计算这个callback对应的下次VSync唤醒的时间,但是入参callback因为我们刚刚计算过,所以不需要要调用update重新计算。轮询callback找到一个最早的时间来做为定时器需要设置的时间,然后调用setTimer重置定时器。

cpp 复制代码
void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor(
        nsecs_t now, CallbackMap::iterator const& skipUpdateIt) {
    std::optional<nsecs_t> min;
    std::optional<nsecs_t> targetVsync;
    std::optional<std::string_view> nextWakeupName;
    // 遍历所有callback,
    for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
        auto& callback = it->second;
        // wakeupTime是schedule计算出来的时间,PendingWorkloadUpdate是之前存储的唤醒时间
        if (!callback->wakeupTime() && !callback->hasPendingWorkloadUpdate()) {
            continue;
        }
        // 如果不是入参的callback,重新计算该callback的VSync(入参的callback才刚刚计算过,不需要重新计算)
        if (it != skipUpdateIt) {
            callback->update(*mTracker, now);
        }
        // 找到一个最早的时间
        auto const wakeupTime = *callback->wakeupTime();
        if (!min || *min > wakeupTime) {
            nextWakeupName = callback->name();
            min = wakeupTime;
            targetVsync = callback->targetVsync();
        }
    }
    // 如果最早的时间比之前设定的mIntendedWakeupTime早,就重新配置计时器。
    if (min && min < mIntendedWakeupTime) {
        if (ATRACE_ENABLED() && nextWakeupName && targetVsync) {
            ftl::Concat trace(ftl::truncated<5>(*nextWakeupName), " alarm in ", ns2us(*min - now),
                            "us; VSYNC in ", ns2us(*targetVsync - now), "us");
            ATRACE_NAME(trace.c_str());
        }
        // 重新配置计数器,详见2.3.5
        setTimer(*min, now);
    } else {
        ATRACE_NAME("cancel timer");
        cancelTimer();
    }
}

2.3.5 VSyncDispatchTimerQueue::setTimer

TimeKeeper的本质就是对linux系统调用timerfd_settime进行封装,实现一个定时器的功能。这里就是根据之前计算的VSync时间设置一个定时器,定时器到了就回调timerCallback方法。

c 复制代码
void VSyncDispatchTimerQueue::setTimer(nsecs_t targetTime, nsecs_t /*now*/) {
    mIntendedWakeupTime = targetTime;
    // 这里TimeKeeper实际是调用linux的系统调用timerfd_settime来配置计时器,我们就不细看了。
    // 等VSync时间到了,回调VSyncDispatchTimerQueue::timerCallback,详见2.3.6
    mTimeKeeper->alarmAt(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
                        mIntendedWakeupTime);
    mLastTimerSchedule = mTimeKeeper->now();
}

2.3.6 VSyncDispatchTimerQueue::timerCallback

这个方法主要的逻辑就是根据callback.wakeupTime来判断这个callback是否需要立刻回调。如果需要就封装到一个Invocation,再push到一个队列里,轮询回调。同时由于当前计时器已经触发,需要重新调用rearmTimerSkippingUpdateFor来确认是否需要配置下一个计时器。

c 复制代码
void VSyncDispatchTimerQueue::timerCallback() {
    struct Invocation {
        std::shared_ptr<VSyncDispatchTimerQueueEntry> callback;
        nsecs_t vsyncTimestamp;
        nsecs_t wakeupTimestamp;
        nsecs_t deadlineTimestamp;
    };
    std::vector<Invocation> invocations;
    {
        std::lock_guard lock(mMutex);
        auto const now = mTimeKeeper->now();
        mLastTimerCallback = now;
        for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
            auto& callback = it->second;
            // 如果需要回调的wakeupTime一定不为空。
            auto const wakeupTime = callback->wakeupTime();
            if (!wakeupTime) {
                continue;
            }

            auto const readyTime = callback->readyTime();

            auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
            // 根据wakeupTime判断这个callback是否需要回调,如果需要则封装到Invocation
            if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
                callback->executing();
                invocations.emplace_back(Invocation{callback, *callback->lastExecutedVsyncTarget(),
                                                    *wakeupTime, *readyTime});
            }
        }

        mIntendedWakeupTime = kInvalidTime;
        // 重置计时器,实际调用还是rearmTimerSkippingUpdateFor,详见之前2.3.4
        rearmTimer(mTimeKeeper->now());
    }

    // 之前判断过需要当前触发的callback都封装存储到invocations,现在开始回调。
    for (auto const& invocation : invocations) {
        详见2.3.7
        invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp,
                                    invocation.deadlineTimestamp);
    }
}

2.3.7 VSyncDispatchTimerQueueEntry::callback

这个mCallback是VSyncDispatchTimerQueueEntry构造时传入的。

这里的构造链路:

EventThread::onNewVsyncSchedule里构造VSyncCallbackRegistration

-》VSyncCallbackRegistration构造时构造了VSyncDispatchTimerQueueEntry

-》VSyncDispatchTimerQueueEntry构造传入了mCallback

由此我们也可以看出来,VSyncDispatchTimerQueue里面的callback其实是和EventThread一一关联的。

c 复制代码
void VSyncDispatchTimerQueueEntry::callback(nsecs_t vsyncTimestamp, nsecs_t wakeupTimestamp,
                                            nsecs_t deadlineTimestamp) {
    {
        std::lock_guard<std::mutex> lk(mRunningMutex);
        mRunning = true;
    }
    // 这个mCallback是VSyncDispatchTimerQueueEntry构造时传入的。
    // 这里的构造链路是EventThread::onNewVsyncSchedule里构造VSyncCallbackRegistration
    // VSyncCallbackRegistration构造时构造了VSyncDispatchTimerQueueEntry
    // VSyncDispatchTimerQueueEntry构造传入了mCallback
    mCallback(vsyncTimestamp, wakeupTimestamp, deadlineTimestamp);

    std::lock_guard<std::mutex> lk(mRunningMutex);
    mRunning = false;
    mCv.notify_all();
}


scheduler::VSyncCallbackRegistration EventThread::onNewVsyncScheduleInternal(
    std::shared_ptr<scheduler::VsyncSchedule> schedule) {
// 。。。
auto oldRegistration =
        std::exchange(mVsyncRegistration,
                      scheduler::VSyncCallbackRegistration(mVsyncSchedule->getDispatch(),
                      // mCallback就是createDispatchCallback,详见2.3.8
                                                           createDispatchCallback(),
                                                           mThreadName));
// 。。。
return oldRegistration;

2.3.8 EventThread::createDispatchCallback()

mCallback其实就是回调EventThread::onVsync

c 复制代码
scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
    return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        // 所以2.3.7 的mCallback就是回调EventThread::onVsync,详见2.3.9
        onVsync(vsyncTime, wakeupTime, readyTime);
    };
}

2.3.9 EventThread::onVsync

构造一个VSync的Event,放在mPendingEvents队列里,然后唤醒2.3 EventThread::threadMain来处理这个事件,到此我们就介绍完了一个VSync信号是怎么产生的。接下去我们看下分发回应用的逻辑。

c 复制代码
void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
    std::lock_guard<std::mutex> lock(mMutex);
    mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime);

    LOG_FATAL_IF(!mVSyncState);
    mVsyncTracer = (mVsyncTracer + 1) % 2;
    // 构造了一个VSync事件,放在mPendingEvents
    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, wakeupTime, ++mVSyncState->count,
                                    vsyncTime, readyTime));
    // 唤醒2.3 EventThread::threadMain来处理这个事件。
    mCondition.notify_all();
}

2.4 EventThread::dispatchEvent

我们接着2.3 threadMain里面调用dispatchEvent来分发VSync事件的逻辑继续看。

由2.3我们可以知道这里consumers都是调用过requestNextVSync的EventThreadConnection。

c 复制代码
status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
    // 。。。
    // 通过BitTube通道发送事件。
    auto size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
    return toStatus(size);
}

发送的app的详细的内容请看上一篇内容android 图形学之 Vsync信号通知产生图层(六)

3.4 MessageQueue::onNewVsyncScheduleLocked

这里的链路实际是在Scheduler初始化时,调用initVsync->onNewVsyncSchedule->onNewVsyncScheduleLocked,但是我们不关注这些,直接来看传入mCallback的地方MessageQueue::onNewVsyncScheduleLocked。

可以看到最终回调方法是MessageQueue::vsyncCallback

c 复制代码
std::unique_ptr<scheduler::VSyncCallbackRegistration> MessageQueue::onNewVsyncScheduleLocked(
        std::shared_ptr<scheduler::VSyncDispatch> dispatch) {
    const bool reschedule = mVsync.registration &&
            mVsync.registration->cancel() == scheduler::CancelResult::Cancelled;
    auto oldRegistration = std::move(mVsync.registration);
    mVsync.registration = std::make_unique<
            scheduler::VSyncCallbackRegistration>(std::move(dispatch),
                                                // MessageQueue::vsyncCallback是传入的回调,详见3.5
                                                std::bind(&MessageQueue::vsyncCallback, this,
                                                            std::placeholders::_1,
                                                            std::placeholders::_2,
                                                            std::placeholders::_3),
                                                "sf");
    if (reschedule) {
        mVsync.scheduledFrameTime =
                mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                            .readyDuration = 0,
                                            .earliestVsync = mVsync.lastCallbackTime.ns()});
    }
    return oldRegistration;
}

3.5 MessageQueue::vsyncCallback

封装来一下VSync的参数,调用了Handler::dispatchFrame

c 复制代码
void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) {
    ATRACE_CALL();
    // Trace VSYNC-sf
    mVsync.value = (mVsync.value + 1) % 2;

    const auto expectedVsyncTime = TimePoint::fromNs(vsyncTime);
    {
        std::lock_guard lock(mVsync.mutex);
        mVsync.lastCallbackTime = expectedVsyncTime;
        mVsync.scheduledFrameTime.reset();
    }

    const auto vsyncId = VsyncId{mVsync.tokenManager->generateTokenForPredictions(
            {targetWakeupTime, readyTime, vsyncTime})};
    // 详见3.6
    mHandler->dispatchFrame(vsyncId, expectedVsyncTime);
}  

3.6 MessageQueue::Handler::dispatchFrame

post了一个消息,我们来看handleMessage处理消息的地方。

c 复制代码
void MessageQueue::Handler::dispatchFrame(VsyncId vsyncId, TimePoint expectedVsyncTime) {
    if (!mFramePending.exchange(true)) {
        mVsyncId = vsyncId;
        mExpectedVsyncTime = expectedVsyncTime;
        // 往looper里发送来一个消息,在handleMessage处理,详见3.7
        mQueue.mLooper->sendMessage(sp<MessageHandler>::fromExisting(this), Message());
    }
}

3.7 MessageQueue::Handler::handleMessage

调用MessageQueue::onFrameSignal,这里的MessageQueue是Scheduler实例,所以调用的是Scheduler::onFrameSignal

c 复制代码
void MessageQueue::Handler::handleMessage(const Message&) {
    mFramePending.store(false);
    // 详见3.8
    mQueue.onFrameSignal(mQueue.mCompositor, mVsyncId, mExpectedVsyncTime);
}

3.8 Scheduler::onFrameSignal

到这里SurfaceFlinger就收到了VSync,并且开始处理了,SurfaceFlinger收到VSync信号主要做的处理就是合成surface。

c 复制代码
void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
                          TimePoint expectedVsyncTime) {
    const TimePoint frameTime = SchedulerClock::now();
    // 做合成的一些预处理,判断flag决策是否需要合成
    if (!compositor.commit(frameTime, vsyncId, expectedVsyncTime)) {
        return;
    }
    // 触发合成。
    compositor.composite(frameTime, vsyncId);
    compositor.sample();
}

参考VSYNC信号的文章

通过trace加深理解 Begin

所以Sf接收到跨进程transaction的请求后申请vsync,计算出来的vsync时间,从而得出wakeupTime,一般这里的wakeupTime会大于前面app

Vsync时候定时的wakeupTime,所以这里不会进行任何的定时。

结合trace看看vsync的情况:

sf的vsync申请触发部分情况:

app vsync一起合作的解释部分:

这里展开一下app ,sf都被回调的trace,对应的代码就是上面的timeCallback方法:

4、app vsync结束部分

vsync有申请就肯定有结束,不可能app没有申请情况下,vsync还一直不断的运行,这样对于系统的功耗影响巨大,而且也是无用功,所以vsync坚持的原则就是有需要用时候app主动申请,不需要了就停止。

上面只分析了vsync怎么开始的,接下来分析vsync的结束部分逻辑

逻辑是如下情况:

时间到了timeCallback

-----》在onVsyncCallback里面会唤醒EventThread

-------》EventThread运行,但是因为没有app进行requestVsync了,所以vsyncRequest = 0

-----》EventThread继续执行时候发现没有vsyncRequest,故需要调用setVsyncEnbale(false)关闭定时

关闭定时器步骤trace:

该部分对应核心代码回顾:

app的EventThread执行时候,会把vsyncRequest变成0,代表没有app的vsync请求了

cpp 复制代码
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
    DisplayEventConsumers consumers;

    while (mState != State::Quit) {
        std::optional<DisplayEventReceiver::Event> event;
        ATRACE_FORMAT("threadMain");


        bool vsyncRequested = false;

        // Find connections that should consume this event.
        auto it = mDisplayEventConnections.begin();
        while (it != mDisplayEventConnections.end()) {
            if (const auto connection = it->promote()) {
            //这里会进行遍历connection,有vsync那么就为true,没有就是false
                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
                //注意这里会对每个connection的vsyncRequest进行改变,注意这里的需要event不为null
                if (event && shouldConsumeEvent(*event, connection)) {
                    consumers.push_back(connection);

                }

                ++it;
            } else {
                it = mDisplayEventConnections.erase(it);
            }
        }
        }

//这个方法里面会改变每个connection的vsyncRequest
bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
                                     const sp<EventThreadConnection>& connection) const {
    switch (event.header.type) {


        case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {
            return connection->mEventRegistration.test(
                    ISurfaceComposer::EventRegistration::modeChanged);
        }

        case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
            switch (connection->vsyncRequest) {
                case VSyncRequest::None:
                    return false;
                    //第一次SingleSuppressCallback后,就改成None
                case VSyncRequest::SingleSuppressCallback:
                    connection->vsyncRequest = VSyncRequest::None;
                    return false;
                case VSyncRequest::Single: {
                    if (throttleVsync()) {
                        return false;
                    }
                    //第一次Single后,就改成SingleSuppressCallback
                    connection->vsyncRequest = VSyncRequest::SingleSuppressCallback;
                    return true;
                }
                case VSyncRequest::Periodic:
                    if (throttleVsync()) {
                        return false;
                    }
                    return true;
                default:
                    return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
            }

    }
}

通过trace加深理解 End

详细的链接看这里:https://h89.cn/archives/293.html

相关推荐
MiyamuraMiyako2 小时前
Compose:从自动滚动到双锚点 LazyLayout
android·android jetpack
用户63421419935074 小时前
base_logger_core --- 跨平台 C++ 日志核心库
android
苦瓜花4 小时前
【Kotlin】初入门
android·开发语言·kotlin
dora5 小时前
使用 Cling 实现 DLNA 投屏:从局域网发现到媒体播放控制
android·android things·tvos
apihz6 小时前
全球域名 WHOIS 信息实时查询免费 API 接口教程,支持1000+后缀
android·网络·网络协议·tcp/ip·apache·域名·whois
非典型Android程序员8 小时前
Binder机制学习总结
android
AI2中文网8 小时前
App Inventor 2 音频播放器 vs 音效 vs 视频播放器:三个媒体组件,选错了App直接卡死
android·音视频·媒体
李剑一8 小时前
uni-app x 实现本地 JSON 文件的导入导出(APP端可用)
android·前端·uni-app
喜欢打篮球的普通人8 小时前
LLVM后端指令选择
android·java·javascript