实现SurfaceFlinger的主动刷新

本文深入探讨SurfaceFlinger如何处理Vsync事件,从SurfaceFlinger.cpp的init()开始,详细解析EventThread的工作流程,通过修改EventThread::Connection的count实现每个Vsync事件都调用handleMessageInvalidate()。
摘要由CSDN通过智能技术生成

实现SurfaceFlinger的主动刷新

Abstract

SurfaceFlinger在收到来自硬件层的Vsync事件之后,不是每次都会调用SurfaceFlinger::handleMessageInvalidate()的。而SurfaceFlinger中处理Vsync事件涉及到的类有:DispSyncThread, DispSync, SurfaceFlinger::DispSyncSource, EventThread, EventThread::Connection, MessageQueue.

本文首先研究这些类之间的关系,以及自Vysnc事件发生后这些类的处理流程。最终,通过修改EventThread::Connection中的成员count实现了每个Vsync事件都会调用SurfaceFlinger::handleMessageInvalidate()的功能。

Process

从SurfaceFlinger.cpp的init()开始

在SurfaceFlinger.cpp的init()方法中,通过如下的代码初始化了DispSyncSource和EventThread,并将mSFEventThread关联到成员变量MessageQueue mEventQueue中:

sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
      vsyncPhaseOffsetNs, true, "app");
mEventThread = new EventThread(vsyncSrc, *this, false);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
      sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
mEventQueue.setEventThread(mSFEventThread);

在EventThread.cpp中可以看到当EventThread的实例创建时,在其onFirstRef()中会开启线程:

void EventThread::onFirstRef() {
    run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}

而在MessageQueue::setEventThread()中,会创建EventThread::Connection:

void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
   if (mEventThread == eventThread) {
      return;
   }

   if (mEventTube.getFd() >= 0) {
      mLooper->removeFd(mEventTube.getFd());
   }

   mEventThread = eventThread;
   mEvents = eventThread->createEventConnection();
   mEvents->stealReceiveChannel(&mEventTube);
   mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
         MessageQueue::cb_eventReceiver, this);
}
sp<EventThread::Connection> EventThread::createEventConnection() const {
    return new Connection(const_cast<EventThread*>(this));
}

EventThread::Connection::Connection(
      const sp<EventThread>& eventThread)
   : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {}

注意 count的初始值是-1
EventThread::ConnectiononFirstConnection中,会将Connection的实例传给EventThread,并加到其成员变量mDisplayEventConnections:

void EventThread::Connection::onFirstRef() {
   mEventThread->registerDisplayEventConnection(this);
}

status_t EventThread::registerDisplayEventConnection(
      const sp<EventThread::Connection>& connection) {
   Mutex::Autolock _l(mLock);
   mDisplayEventConnections.add(connection);

   if (!mFirstConnectionInited) {
      // additional external displays can't be enumerated by default,
      // need to report additional hotplug to listeners
      for (int32_t type = DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES;
            type < (int32_t)mHotplugEvent.size(); type++) {
         if (mHotplugEvent[type].hotplug.connected) {
               connection->postEvent(mHotplugEvent[type]);
         }
      }
      mFirstConnectionInited = true;
   }

   mCondition.broadcast();
   return NO_ERROR;
}

第一次执行EventThread::waitForEvent()

EventThread::threadLoop()运行起来后,首先会执行EventThread::waitForEvent()方法:

Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
      DisplayEventReceiver::Event* event)
{
   Mutex::Autolock _l(mLock);
   Vector< sp<EventThread::Connection> > signalConnections;

   do {
      bool eventPending = false;
      bool waitForVSync = 
Android 中,View 是用户界面的基本组件,用于显示和处理用户界面上的各种元素。Android 13 中的 SurfaceFlinger 通过与 View 系统进行协作来实现定时刷新 View 的功能。 具体来说,Android 中的 View 系统提供了一个名为 Choreographer 的系统服务,它可以帮助应用程序实现定时刷新 View 的功能。Choreographer 可以协调应用程序中各种动画和 UI 事件的执行顺序,并在每一帧结束时向 SurfaceFlinger 发送 VSync 信号,从而触发 SurfaceFlinger 开始下一帧的渲染。 当应用程序中的某个 View 需要进行定时刷新时,可以通过以下步骤来实现: 1. 在 View 中创建一个 Choreographer.FrameCallback 对象,并重写其 doFrame() 方法来实现 View 的刷新逻辑; 2. 在 View 中注册 FrameCallback 对象,以便在每一帧结束时得到回调通知; 3. 在 View 的生命周期中,通过 Choreographer.getInstance().postFrameCallback(FrameCallback) 方法来注册和注销 FrameCallback 对象。 以下是一个示例代码: ```java public class MyView extends View implements Choreographer.FrameCallback { private Choreographer mChoreographer; public MyView(Context context) { super(context); mChoreographer = Choreographer.getInstance(); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); mChoreographer.postFrameCallback(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); mChoreographer.removeFrameCallback(this); } @Override public void doFrame(long frameTimeNanos) { // 在这里实现 View 的刷新逻辑 // ... // 重新注册 FrameCallback 对象 mChoreographer.postFrameCallback(this); } } ``` 在上述代码中,我们首先创建了一个 MyView 类,它继承自 View 类,并实现了 Choreographer.FrameCallback 接口。在 MyView 中,我们在 onAttachedToWindow() 方法中注册了 FrameCallback 对象,并在 onDetachedFromWindow() 方法中注销了 FrameCallback 对象。在 doFrame() 方法中,我们实现了 View 的刷新逻辑,并在最后重新注册了 FrameCallback 对象以实现定时刷新的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值