Vsync与app、surfaceFlinger关系(1)

app要进行更新,必须先要请求一个vsync,等到下个vsync信号来的时候进行界面的更新。
一、首先先看一下app请求vsync。
我们熟知的TextView.setText 或者ImageView.setImageBitmap,最后都要执行invalidate申请重绘,最后会通过ViewParent递归到ViewRootImpl的invalidate。Choreographer.postCallback进行vsync信号的申请。最终胡通过IDisplayEventConnection.cpp 的requestNextVsync,调用到服务端EventThread的requestNextVsync();
流程图如下:

18.png

流程比较简单,最终就是调用了一个 mChoreographer.postCallback

frameworks/base/core/java/android/view/ViewRootImpl.java
      @UnsupportedAppUsage
      void scheduleTraversals() {
          if (!mTraversalScheduled) {
              mTraversalScheduled = true;
              mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); @1
              mChoreographer.postCallback(
                      Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); @2
              notifyRendererOfFramePending();
              pokeDrawLockIfNeeded();
          }
      }

@1 设置同步栅栏,拦截同步消息
@2 来请求请求vnsc垂直同步信号,

二、Choreograhper接下来的流程如下图:

19.png

看下几个重要方法
1、
scheduleFrameLocked可以被调用多次,但是mFrameScheduled保证下一个vsync到来之前,不会有新的请求发出,多余的scheduleFrameLocked调用被无效化

frameworks/base/core/java/android/view/Choreographer.java
private void scheduleFrameLocked(long now) {
    if (!mFrameScheduled) {   
        mFrameScheduled = true;
......
        if (ScrollOptimizer.shouldUseVsync(USE_VSYNC)) {
        ......
            if (isRunningOnLooperThreadLocked()) {
                scheduleVsyncLocked();
            } else {
                // 设置此message为异步消息,因为之前已经设置了同步屏障,所以异步消息会优先执行。
                Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
                msg.setAsynchronous(true);
                mHandler.sendMessageAtFrontOfQueue(msg);
            }
        }  
    }
}

2、
最终要的就是最后一步,在IDisplayEventConnection.cpp中的requestNextVsync方法

framworks/native/libs/gui/IDisplayEventConnection.cpp
      void requestNextVsync() override {
          callRemoteAsync<decltype(&IDisplayEventConnection::requestNextVsync)>(
                  Tag::REQUEST_NEXT_VSYNC);
      }
  };

这块CallRemoteAsync,异步binder调用到服务端,会执行服务端的onTransact方法,这个过程是夸进程的。

status_t BnDisplayEventConnection::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                                uint32_t flags) {
      if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
          return BBinder::onTransact(code, data, reply, flags);
      }
      auto tag = static_cast<Tag>(code);
      switch (tag) {
          case Tag::STEAL_RECEIVE_CHANNEL:
              return callLocal(data, reply, &IDisplayEventConnection::stealReceiveChannel);
          case Tag::SET_VSYNC_RATE:
              return callLocal(data, reply, &IDisplayEventConnection::setVsyncRate);
          case Tag::REQUEST_NEXT_VSYNC: @1
              return callLocalAsync(data, reply, &IDisplayEventConnection::requestNextVsync);
      }
  }

在@1处会调用到 EventThreadConnection的 requestNextVsync。

21.png

很明显,BpDisplayEventConnection 的requestNextVsync 会binder调用到BnDisplayEventConnection的requestNextVsync。也就是夸进程,从app进程到surfaceFlinger进程。

看一下各自的位置
frameworks/native/libs/gui/DisplayEventReceiver.cpp

Client端:

class BpDisplayEventConnection : public SafeBpInterface<IDisplayEventConnection> {
......
}  在frameworks/native/libs/gui/IDisplayEventConnection.cpp 中

server端:

class EventThreadConnection : public BnDisplayEventConnection {
.....
}  在frameworks/native/services/surfaceflinger/scheduler/eventThread.h 中

class BnDisplayEventConnection : public SafeBnInterface<IDisplayEventConnection> {
......
}  在frameworks/native/include/gui/IDisplayEventConnection.h

三、接下来看下服务端(EventThreadConnection)的requestNextVsync

void EventThreadConnection::requestNextVsync() {
      ATRACE_NAME("requestNextVsync");
      mEventThread->requestNextVsync(this);
  }

会调用EventThread的requestNextVsync

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();   @1
      }
  }

因为 threadMain中的循环在EventThread的构造方法中已经启动,此时@1出的notify_call就会唤醒其 mConditioni.wait(lock),进入下一次循环,这时候就会执行 mVSyncSource->setVsyncEnable(true);

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);    @2
              }
              mState = nextState;
          }

          if (event) {
              continue;
          }
  
          // Wait for event or client registration/request.
          if (mState == State::Idle) {
              mCondition.wait(lock);   @3
          } 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.
......

@3处就会等待下一次requestVsync信号过来进行唤醒,会进行下一次循环,经过一系列的操作,会执行 mVSyncSource->setVSyncEnabled(true);

frameworks/native/services/surfaceflinger/scheduler/DispSyncSource.cpp
void DispSyncSource::setVsyncEnabled(bool enable){
std::lock_gurad lock(mVsyncMutex);
If(enable){   @4
    status_t err = mDispSync->addEventlistener(mName,mPhaseOffset,static_cast<DispSync::Callback*>(this),mLastCallbackTime); @1
If(err != No_ERROE){
    ALOGE(“error registering vsync callback: %s (%d)”,strerror(-err),err);
}
}else{
   status_t err = mDispSync->removeEventlistener(mName,mPhaseOffset,static_cast<DispSync::Callback*>(this),mLastCallbackTime);
If(err != No_ERROE){
    ALOGE(“error unregistering vsync callback: %s (%d)”,strerror(-err),err);
}
  If(mDolphinCheck){
If(mDolphinCheck(mName)){
  status_t err = mDispSync->addEventlistener(mName,mPhaseOffset,static_cast<DispSync::Callback*>(this),mLastCallbackTime);
If(err != No_ERROE){
    ALOGE(“error registering vsync callback: %s (%d)”,strerror(-err),err);
}

}
}
}
mEnable = enable
}

在@4处 enable 为true的时候,会执行mDispSync->addEventListener注册一个vsync监听

system/native/services/surfaceflinger/scheduler/DispSync.cpp

    status_t addEventListener(const char* name, nsecs_t phase, DispSync::Callback* callback,
                              nsecs_t lastCallbackTime) {
        if (mTraceDetailedInfo) ATRACE_CALL();
        Mutex::Autolock lock(mMutex);

        for (size_t i = 0; i < mEventListeners.size(); i++) {
            if (mEventListeners[i].mCallback == callback) {
                return BAD_VALUE;
            }
        }

        EventListener listener;
        listener.mName = name;
        listener.mPhase = phase;
        listener.mCallback = callback;

        // We want to allow the firstmost future event to fire without
        // allowing any past events to fire. To do this extrapolate from
        // mReferenceTime the most recent hardware vsync, and pin the
        // last event time there.
        const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        if (mPeriod != 0) {
            const nsecs_t baseTime = now - mReferenceTime;
            const nsecs_t numPeriodsSinceReference = baseTime / mPeriod;
            const nsecs_t predictedReference = mReferenceTime + numPeriodsSinceReference * mPeriod;
            const nsecs_t phaseCorrection = mPhase + listener.mPhase;
            const nsecs_t predictedLastEventTime = predictedReference + phaseCorrection;
            if (predictedLastEventTime >= now) {
                // Make sure that the last event time does not exceed the current time.
                // If it would, then back the last event time by a period.
                listener.mLastEventTime = predictedLastEventTime - mPeriod;
            } else {
                listener.mLastEventTime = predictedLastEventTime;
            }
        } else {
            listener.mLastEventTime = now + mPhase - mWakeupLatency;
        }

        if (lastCallbackTime <= 0) {
            // If there is no prior callback time, try to infer one based on the
            // logical last event time.
            listener.mLastCallbackTime = listener.mLastEventTime + mWakeupLatency;
        } else {
            listener.mLastCallbackTime = lastCallbackTime;
        }

        mEventListeners.push_back(listener);@1

        mCond.signal();

        return NO_ERROR;
}

传进来的参数name, phase, callback, lastCallbackTime 都会赋值给一个EventListener对象,然后@1处 存入一个vector类型的集合。这样app 的 vsync信号就算注册好了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值