android 12 中的VSYNC接收

初始化:SurfaceFlinger::init()

SurfaceFlinger 复制代码
//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));

这个调用会触发一系列对象的创建,它们之间的关系如下:

1. 工厂创建:impl::HWComposer

getFactory().createHWComposer() 会创建 impl::HWComposer 对象。

它的构造函数有两个版本:

  • 直接构造impl::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
  • 通过服务名构造impl::HWComposer(const std::string& composerServiceName)

后者是常用路径,它会内部创建一个 Hwc2::impl::Composer 实例。

HWComposer 复制代码
//frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
namespace impl {
  
  HWComposer::HWComposer(const std::string& composerServiceName)
        : HWComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) {}
 

此时,impl::HWComposer 持有了一个 Hwc2::impl::Composer 对象(类型为 std::unique_ptr<Hwc2::Composer>)。

2. 连接 HAL:Hwc2::impl::Composer

Hwc2::impl::Composer 的构造函数会去连接 Composer HAL 服务

VSYNC 信号接收:从硬件中断到 SurfaceFlinger

SurfaceFlinger 通过实现 ComposerCallback 接口来直接接收回调。

1. 注册回调:setCallback

SurfaceFlinger::init() 中,紧接着创建 HWComposer 之后,会调用:

SurfaceFlinger 复制代码
//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp 
mCompositionEngine->getHwComposer().setCallback(this);

这里的 thisSurfaceFlinger 实例,它实现了 HWC2::ComposerCallback 接口。

impl::HWComposer::setCallback() 内部会将回调注册到 HAL 层。在 HIDL 实现中,会创建一个 ComposerCallbackBridge 对象,它将 SurfaceFlinger 的回调适配给 HAL 层的 IComposerCallback 接口。

2. 回调:onComposerHalVsync

当硬件 VSYNC 中断发生时,HAL 服务会回调 IComposerCallback 接口的 onVsync 方法。

这个调用最终会通过 ComposerCallbackBridge 等适配层,转换成对 SurfaceFlinger::onComposerHalVsync() 的调用。

接收到VSYNC后的处理流程:

第一步:SurfaceFlinger::onComposerHalVsync()

SurfaceFlinger 复制代码
//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp 
void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp,
                                          std::optional<hal::VsyncPeriodNanos> vsyncPeriod) {
      ATRACE_CALL();
  
      Mutex::Autolock lock(mStateLock);
 
      //通知HWC模块,将HWC的display ID转换为SF内部的display ID
      if (const auto displayId = getHwComposer().toPhysicalDisplayId(hwcDisplayId)) {
          auto token = getPhysicalDisplayTokenLocked(*displayId);
          auto display = getDisplayDeviceLocked(token);
          display->onVsync(timestamp);
      }
  
      if (!getHwComposer().onVsync(hwcDisplayId, timestamp)) {
          return;
      }
  
      if (hwcDisplayId != getHwComposer().getInternalHwcDisplayId()) {
          // For now, we don't do anything with external display vsyncs.
          return;
      }
  
      bool periodFlushed = false;
      
      //将时间戳作为样本,交给Scheduler处理
      mScheduler->addResyncSample(timestamp, vsyncPeriod, &periodFlushed);
      if (periodFlushed) {
          //如果VSYNC周期有变化,则进行相应调整
          modulateVsync(&VsyncModulator::onRefreshRateChangeCompleted);
      }
  }

SurfaceFlinger 接收到 VSYNC 后,会将其交给 Scheduler 组件进行后续的调度和分发,驱动画面合成。

第二步:Scheduler::addResyncSample() --- 样本注入与开关决策

Scheduler 接收到时间戳后,通过 VSyncReactor 进行实际处理,并根据返回值决定是否关闭硬件 VSYNC

Scheduler 复制代码
//frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp)
 void Scheduler::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
                                   bool* periodFlushed) {
       bool needsHwVsync = false;
       *periodFlushed = false;
       { // Scope for the lock
           std::lock_guard<std::mutex> lock(mHWVsyncLock);
           if (mPrimaryHWVsyncEnabled) {
           
               //将时间戳传递给 VSyncReactor
               // mVsyncSchedule.controller 的实际类型是 VSyncReactor
               needsHwVsync = mVsyncSchedule.controller->addHwVsyncTimestamp(timestamp, hwcVsyncPeriod,
                                                                             periodFlushed);
           }
       }
   
       
       //根据返回值决定是否继续开启硬件 VSYNC
       if (needsHwVsync) {
           //继续保持硬件中断
           enableHardwareVsync();
       } else {
          // 关闭硬件中断,切换到软件预测模式
           disableHardwareVsync(false);
       }
   }
   
  

第三步:VSyncReactor::addHwVsyncTimestamp() --- 模型更新

VSyncReactor 是信号处理的中枢。它接收时间戳后,主要工作是将其喂给 VSyncTracker(即 VSyncPredictor)来训练预测模型

VSyncReactor 复制代码
//frameworks/native/services/surfaceflinger/Scheduler/VSyncReactor.cpp
  bool VSyncReactor::addHwVsyncTimestamp(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
                                          bool* periodFlushed) {
      
   
      ....
      //将时间戳喂给 `VSyncPredictor`,用于训练 VSYNC 预测模型。
      // mTracker = VSyncPredictor
      mTracker.addVsyncTimestamp(timestamp);
     ....
         
     
      //返回是否需要更多样本(即是否需要继续开启硬件 VSYNC)
      return mMoreSamplesNeeded; 

   }
   

第四步:VSyncPredictor::addVsyncTimestamp() --- 模型训练

VSyncPredictor 维护一个历史样本队列,基于这些样本计算出稳定的 VSYNC 周期和相位

arduino 复制代码
bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) {
    // 将时间戳加入样本队列
    // 当样本足够多时,计算出稳定的周期(period)和相位(phase)
    // 更新内部模型参数
    // 返回模型是否已稳定(即不再需要更多硬件样本)
    
}

当模型稳定后,VSyncPredictor 会通知 VSyncReactor,后者返回 false,从而触发 Scheduler::disableHardwareVsync(),关闭硬件 VSYNC 以省电

第五步:VSyncDispatchTimerQueue --- 软件 VSYNC 调度

当硬件 VSYNC 关闭后,系统进入省电的软件 VSYNC 模式。此时,VSyncDispatchTimerQueueVSyncDispatch 的实现类)根据 VSyncPredictor 的预测结果,通过定时器驱动 VSYNC 分发。

5.1 注册回调 :在 SurfaceFlinger::initScheduler() 中,EventThread 通过 VSyncCallbackRegistrationVSyncDispatch 注册回调)。

5.2 请求调度EventThread 需要下一个 VSYNC 信号时,调用 VSyncDispatch::schedule(),计算下一次唤醒时间并设置定时器。

5.3 定时器触发 :定时器到达后,调用 VSyncDispatchTimerQueue::timerCallback()

VSyncDispatchTimerQueue 复制代码
//frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
void VSyncDispatchTimerQueue::timerCallback() {
    // 遍历所有已注册且到期的 VSyncDispatchTimerQueueEntry
    // 调用其 callback() 方法
}

5.4 执行回调callback() 会沿着 DispSyncSourceEventThreadMessageQueue 的链路传递。

第六步:EventThread 分发 VSYNC

EventThread 负责将 VSYNC 事件分发给所有已注册的监听者。

EventThread 复制代码
//frameworks/native/services/surfaceflinger/EventThread.cpp
void EventThread::onVSyncEvent(nsecs_t timestamp) {
    Mutex::Autolock _l(mLock);
    // 将 VSYNC 事件放入队列
    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
    mVSyncEvent[0].header.timestamp = timestamp;
    // 唤醒等待的线程
    mCondition.broadcast();
}

void EventThread::threadMain() {
    // 主循环:等待事件,然后分发给所有 Connection
    // 遍历 mSignalConnections,调用 Connection::postEvent()
}

第七步:MessageQueue 接收并触发合成

SurfaceFlingerMessageQueueEventThread 注册了回调,当 VSYNC 到来时被触发。

MessageQueue 复制代码
// frameworks/native/services/surfaceflinger/MessageQueue.cpp
void MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
    MessageQueue* queue = reinterpret_cast<MessageQueue*>(data);
    // 发送 REFRESH 消息到 SurfaceFlinger 主线程
    queue->mFlinger->onMessageReceived(MessageQueue::REFRESH);
}

第八步:SurfaceFlinger 执行合成

SurfaceFlinger 主线程收到 REFRESH 消息后,执行实际的画面合成。

arduino 复制代码
//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::onMessageReceived(int32_t what) {
    switch (what) {
        case MessageQueue::REFRESH:
            handleMessageRefresh(); // 执行合成
            break;
        // ...
    }
}

void SurfaceFlinger::handleMessageRefresh() {
    // ... 处理事务、合成图层、送显 ...
    doComposition();
}
相关推荐
GitLqr1 小时前
Flutter 3.44 性能飞跃:深度解析 Android Platform View 的 HCPP 新特性
android·flutter·性能优化
码农coding1 小时前
android 12 SurfaceFlinger中的CompositionEngine
android
Mem0rin3 小时前
[MySQL] 聚合函数、分组查询、连接查询
android·mysql
码龙-DragonCoding3 小时前
一键批量提取音频、提取视频
android·音视频·提取
祉猷并茂,雯华若锦3 小时前
Win下完美解决Allure报错,生成Web自动化测试报告
android·python·selenium·自动化
IT小盘5 小时前
08-FastAPI加MySQL实现AI对话记录持久化
android·mysql·fastapi
alice--小文子5 小时前
安卓(Android)- 怎么在adb中通过真机操作日志相关
android·adb
清泓y5 小时前
Android内存管理与性能优化面试真题
android·面试·性能优化
hopsky5 小时前
Wechatsync 安全审计报告
android·java·安全