当前位置: 首页 > news >正文

Android图像显示SurfaceFlinger总结

1 介绍

1.1 框架中位置

​​Android图像显示系统框架图
上图为Android的图形显示系统框架图。
首先上层应用通过ViewRoot的scheduleTraversals函数发起绘制任务,并通过HWUI调用OpenGL接口将绘制数据传递给GPU处理;SF会接收所有应用更新的绘制数据,并根据Z-Order、透明度、大小、位置等参数计算出每个应用图层在最终合成图像中的位置;SF完成图层处理后会把所有的应用图层提供给HWC,由HWC来决定这些图层的合成策略并调用屏显驱动做合成;最后屏显驱动会将合成的最终画面送到硬件屏幕显示。

Android系统通过buffer缓冲区来保存图形信息,这个buffer的内存空间是有SF向图形内存分配器Gralloc申请的,而Gralloc是通过ION Driver从kernel中开辟出一块共享内存。在整个图形显示流程中,buffer缓冲区会在App、SF、HWC之间来回流转。

1.2 职责

  1. surfaceFlinger是一个服务进程
  2. 负责管理应用程序窗口的创建、显示、更新和销毁等操作
    3)向上和WindowManager交互,向下和HwComposer交互。
    SF会接收所有应用更新的绘制数据,并根据Z-Order、透明度、大小、位置等参数计算出每个应用图层在最终合成图像中的位置;
    SF完成图层处理后会把所有的应用图层提供给HWC,由HWC来决定这些图层的合成策略并调用屏显驱动做合成

负责显示系统界面和应用程序的图形渲染工作。

  • 图像合成:SurfaceFlinger 接收来自多个应用程序和系统服务的图像缓冲区,根据它们的位置、大小、透明度、Z轴顺序等属性,将它们合成到一个最终的缓冲区中,然后发送到显示设备上 。
  • 管理 Surface:SurfaceFlinger 管理所有 Surface 对象,包括视频、图片等,并为每个 Surface 对象分配 BufferQueue(缓冲区队列),确保每个 Surface 都能按时完成显示 。
  • 三缓冲与 VSYNC 机制:SurfaceFlinger 采用双缓冲区机制,即前台和后台两个缓冲区,以及 VSYNC 机制,以提高渲染效率和质量,减少屏幕撕裂现象 。
  • 硬件加速:SurfaceFlinger 提供多种硬件加速技术,如 OpenGL ES、Vulkan 等,使应用程序能够更快地渲染 UI 界面 。
  • 窗口叠加与透明度支持:SurfaceFlinger 支持窗口叠加、透明度、混合模式等特性,以支持复杂的多层 UI 界面 。
  • 与 Hardware Composer 通信:SurfaceFlinger 与硬件抽象层 Hardware Composer 进行通信,利用硬件加速的方式来合成 Surface,提高性能和节省电量 。
  • 处理输入事件:SurfaceFlinger 中的 EventThread 方法负责处理输入事件,将输入事件分发给对应的窗口或 Surface 进行处理

2 源码分析

首先看下系统中SurfaceFlinger的进程
在这里插入图片描述
代码中入口:
SF是一个独立的可执行程序,路径是/system/bin/surfaceflinger,开机过程中init进程会解析surfaceflinger.rc,启动surfaceflinger进程。
frameworks/native/services/surfaceflinger/surfaceflinger.rc,

service surfaceflinger /system/bin/surfaceflingerclass core animationuser systemgroup graphics drmrpc readproccapabilities SYS_NICEonrestart restart --only-if-running zygotetask_profiles HighPerformancesocket pdx/system/vr/display/client     stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0socket pdx/system/vr/display/manager    stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0socket pdx/system/vr/display/vsync      stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0on property:vendor.debug.sf.restart=1restart surfaceflingeron property:init.svc.zygote=restarting && property:debug.sf.toomanylayers=1restart surfaceflingersetprop debug.sf.toomanylayers "0"

2.1 SurfaceFlinger的初始化

init.rc中调用到SF的main函数,这里是SF进程的入口。
路径:frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp

int main(int, char**) {startGraphicsAllocatorService(); //启动图形服务...sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger(); //1. 创建SF实例flinger->init(); //2. 对SF实例进行初始化// publish surface flinger//3. 将SF添加到serviceManager中。 这样客户端通过getService()+SurfaceFlinger的名称,// 就可以获取SF的远程代理对象,进而和SF服务跨进程通信//static char const* getServiceName() ANDROID_API { return "SurfaceFlinger"; } @SurfaceFinger.hsp<IServiceManager> sm(defaultServiceManager());sm->addService(String16(SurfaceFlinger::getServiceName()),  flinger,  false,IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);// publish gui::ISurfaceComposer, the new AIDL interface//4. 新建SurfaceComposerAIDL对象,注册到serviceManager中sp<SurfaceComposerAIDL> composerAIDL = new SurfaceComposerAIDL(flinger);sm->addService(String16("SurfaceFlingerAIDL"), composerAIDL, false,IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);// 启动Display服务startDisplayService(); // dependency on SF getting registered above...// run surface flinger in this threadflinger->run(); //5. 启动SF线程
}

2.2 SurfaceFlinger构造函数详解

先来看下SurfaceFlinger的类关系图
//frameworks/native/services/surfaceflinger/SurfaceFlinger.h
在这里插入图片描述
ISurfaceComposer的接口定义:
它的职责是:

class ISurfaceComposer: public IInterface {
public:DECLARE_META_INTERFACE(SurfaceComposer)static constexpr size_t MAX_LAYERS = 4096;...//Create a connection with SurfaceFlinger.virtual sp<ISurfaceComposerClient> createConnection() = 0;...

2.2.1 createSurfaceFlinger详解

接下来看下surfaceflinger::createSurfaceFlinger()具体做了什么?
新建一个SurfaceFlinger实例,将DefaultFactory 做为参数传入,其中DefaultFactory继承了surfaceflinger::Factory类。
主要做了什么?

  • 创建CompositionEngine
  • 添加了WindowInfosListenerInvoker回调
//frameworks/native/services/surfaceflinger/SurfaceFlingerFactory.cpp
sp<SurfaceFlinger> createSurfaceFlinger() {static DefaultFactory factory;return new SurfaceFlinger(factory);
}SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag): mFactory(factory),mPid(getpid()),mInterceptor(mFactory.createSurfaceInterceptor()),mTimeStats(std::make_shared<impl::TimeStats>()),mFrameTracer(mFactory.createFrameTracer()),mFrameTimeline(mFactory.createFrameTimeline(mTimeStats, mPid)),mCompositionEngine(mFactory.createCompositionEngine()), //创建CompositionEngine...//添加了WindowInfosListenerInvoker回调mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make(*this)) {ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
}
//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
//SurfaceFlinger构造函数中对一些成员变量进行赋值初始化。
SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) {ALOGI("SurfaceFlinger is starting");hasSyncFramework = running_without_sync_framework(true);dispSyncPresentTimeOffset = present_time_offset_from_vsync_ns(0);useHwcForRgbToYuv = force_hwc_copy_for_virtual_displays(false);maxFrameBufferAcquiredBuffers = max_frame_buffer_acquired_buffers(2);...
}

2.2.2 SurfaceFlinger的init详解

flinger->init()对SF实例进行初始化,具体做了什么?

void SurfaceFlinger::init() {ALOGI(  "SurfaceFlinger's main thread ready to run. ""Initializing graphics H/W...");Mutex::Autolock _l(mStateLock);//构造renderengine的builderauto builder = renderengine::RenderEngineCreationArgs::Builder().setPixelFormat(static_cast<int32_t>(defaultCompositionPixelFormat)).setImageCacheSize(maxFrameBufferAcquiredBuffers).setUseColorManagerment(useColorManagement).setEnableProtectedContext(enable_protected_contents(false)).setPrecacheToneMapperShaderOnly(false).setSupportsBackgroundBlur(mSupportsBlur).setContextPriority(useContextPriority? renderengine::RenderEngine::ContextPriority::REALTIME: renderengine::RenderEngine::ContextPriority::MEDIUM);...//创建renderEngine,并给mCompositionEngine设置RenderEnginemCompositionEngine->setRenderEngine(renderengine::RenderEngine::create(builder.build()));...//调用mCompositionEngine来createHWComposer,给mCompositionEngine设置回调函数。思考:这里回调是什么接口?作用是?mCompositionEngine->setTimeStats(mTimeStats);mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));mCompositionEngine->getHwComposer().setCallback(*this);...// Process any initial hotplug and resulting display changes.processDisplayHotplugEventsLocked(); //重要调用,第一次会做一次插拔检测const auto display = getDefaultDisplayDeviceLocked();LOG_ALWAYS_FATAL_IF(!display, "Missing primary display after registering composer callback.");const auto displayId = display->getPhysicalId();LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(displayId),  "Primary display is disconnected.");// initialize our drawing statemDrawingState = mCurrentState; //更新drawState, 思考:其中共有几种状态?都是什么时候切换的?initializeDisplays();...ALOGV("Done initializing");
}

2.2.3 processDisplayHotplugEventsLocked详解

//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::processDisplayHotplugEventsLocked() {for (const auto& event : mPendingHotplugEvents) {std::optional<DisplayIdentificationInfo> info =getHwComposer().onHotplug(event.hwcDisplayId, event.connection);if (!info) { continue; }//获取displayId和token const auto displayId = info->id;const auto token = mPhysicalDisplayTokens.get(displayId);if (event.connection == hal::Connection::CONNECTED) { //如果此时有显示屏幕连接... //} else { //如果此时没有显示屏幕连接ALOGV("Removing display %s", to_string(displayId).c_str());if (const ssize_t index = mCurrentState.displays.indexOfKey(token->get()); index >= 0) {const DisplayDeviceState& state = mCurrentState.displays.valueAt(index);mInterceptor->saveDisplayDeletion(state.sequenceId);mCurrentState.displays.removeItemsAt(index);}mPhysicalDisplayTokens.erase(displayId);}processDisplayChangesLocked(); //主要步骤,处理显示改变}mPendingHotplugEvents.clear();
}void SurfaceFlinger::processDisplayChangesLocked() {const KeyedVector<wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);const KeyedVector<wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);if (!curr.isIdenticalTo(draw)) {mVisibleRegionsDirty = true;// find the displays that were removed (ie: in drawing state but not in current state)// also handle displays that changed (ie: displays that are in both lists)for (size_t i = 0; i < draw.size(); i++) {const wp<IBinder>& displayToken = draw.keyAt(i);const ssize_t j = curr.indexOfKey(displayToken);if (j < 0) {// in drawing state but not in current stateprocessDisplayRemoved(displayToken);} else {// this display is in both lists. see if something changed.const DisplayDeviceState& currentState = curr[j];const DisplayDeviceState& drawingState = draw[i];processDisplayChanged(displayToken, currentState, drawingState); //核心步骤,调用processDisplayAdded}}...}mDrawingState.displays = mCurrentState.displays;
}

2.2.4 processDisplayAdded详解

主要做了几件事:
1)通过CompositionEngine创建display
2)创建BufferQueue 和 DisplaySurface对象
3)调用initscheduler来初始化整个Vsync系统

void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,const DisplayDeviceState& state) {compositionengine::DisplayCreationArgsBuilder builder; builder.setPixels(resolution);builder.setIsSecure(state.isSecure);builder.setPowerAdvisor(mPowerAdvisor.get());builder.setName(state.displayName);// 1. 通过CompositionEngine创建display,具体display参数通过builder设置auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());compositionDisplay->setLayerCachingEnabled(mLayerCachingEnabled);sp<compositionengine::DisplaySurface> displaySurface;sp<IGraphicBufferProducer> producer; //为什么有producer 和BqProducer,两者有什么区别?sp<IGraphicBufferProducer> bqProducer;sp<IGraphicBufferConsumer> bqConsumer;//2. 创建BufferQueuegetFactory().createBufferQueue(&bqProducer, &bqConsumer, /*consumerIsSurfaceFlinger =*/false);//3. 创建DisplaySurface对象if (state.isVirtual()) {const auto displayId = VirtualDisplayId::tryCast(compositionDisplay->getId());auto surface = sp<VirtualDisplaySurface>::make(getHwComposer(), *displayId, state.surface,bqProducer, bqConsumer, state.displayName);displaySurface = surface;producer = std::move(surface);} else {const auto displayId = PhysicalDisplayId::tryCast(compositionDisplay->getId());displaySurface = sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqConsumer,state.physical->activeMode->getResolution(),ui::Size(maxGraphicsWidth, maxGraphicsHeight));producer = bqProducer;}...auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay), state,displaySurface, producer);if (display->isPrimary()) {initScheduler(display); //主要步骤,调用initscheduler来初始化整个Vsync系统}mDisplays.try_emplace(displayToken, std::move(display));
}

2.2.5 initScheduler详解

initscheduler初始化整个Vsync系统,主要做几件事:
1)如果没有mScheduler ,创建mScheduler,有的话直接使用
2)创建APP连接
3)创建SF连接
4)初始化Vsync

void SurfaceFlinger::initScheduler(const sp<DisplayDevice>& display) {if (mScheduler) {// If the scheduler is already initialized, this means that we received// a hotplug(connected) on the primary display. In that case we should// update the scheduler with the most recent display information.ALOGW("Scheduler already initialized, updating instead");mScheduler->setRefreshRateConfigs(display->holdRefreshRateConfigs());return;}//如果没有mScheduler ,创建mSchedulermScheduler = std::make_unique<scheduler::Scheduler>(static_cast<ICompositor&>(*this),static_cast<ISchedulerCallback&>(*this),features);{auto configs = display->holdRefreshRateConfigs();if (configs->kernelIdleTimerController().has_value()) {features |= Feature::kKernelIdleTimer;}mScheduler->createVsyncSchedule(features);mScheduler->setRefreshRateConfigs(std::move(configs));}setVsyncEnabled(false);mScheduler->startTimers();const auto configs = mVsyncConfiguration->getCurrentConfigs();const nsecs_t vsyncPeriod = currRefreshRate.getPeriodNsecs();//创建APP连接mAppConnectionHandle =  mScheduler->createConnection("app", mFrameTimeline->getTokenManager(),/*workDuration=*/configs.late.appWorkDuration,/*readyDuration=*/configs.late.sfWorkDuration,impl::EventThread::InterceptVSyncsCallback());//创建SF连接mSfConnectionHandle = mScheduler->createConnection("appSf", mFrameTimeline->getTokenManager(),/*workDuration=*/std::chrono::nanoseconds(vsyncPeriod),/*readyDuration=*/configs.late.sfWorkDuration,[this](nsecs_t timestamp) {mInterceptor->saveVSyncEvent(timestamp);});//初始化VsyncmScheduler->initVsync(mScheduler->getVsyncDispatch(), *mFrameTimeline->getTokenManager(),configs.late.sfWorkDuration);mFpsReporter = new FpsReporter(*mFrameTimeline, *this); mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, display->getActiveMode());
}

思考几个问题:
1)创建mScheduler的用处?
2)mScheduler->createConnection()具体做了什么?
3)mScheduler->initVsync()做了什么?

2.2.6 mScheduler详解

2.3

3 小结

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【数据结构初阶】二叉树与堆(一)
  • 【CN】Argo 持续集成和交付(二)
  • 为什么要设置 os.environ[“PYTHONHASHSEED“] = “0“,这样做具体会影响哪些随机值?
  • 观察者模式(Observer Pattern)
  • C# 设计模式之桥接模式
  • 新质生产力
  • PHP中如何定义常量以及常量和变量的主要区别
  • 海思35XX系列(三)sensor(传感器)
  • VUE框架面试整理-模板语法
  • EfficientNet-v2-s图像分类训练(简洁版)
  • DataX介绍
  • Python模块中的全局变量
  • Mecanim Animation System
  • Golang | Leetcode Golang题解之第310题最小高度树
  • 音视频入门基础:WAV专题(5)——FFmpeg源码中解码WAV Header的实现
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • CentOS7 安装JDK
  • CSS魔法堂:Absolute Positioning就这个样
  • interface和setter,getter
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • Java应用性能调优
  • Python爬虫--- 1.3 BS4库的解析器
  • webpack入门学习手记(二)
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 半理解系列--Promise的进化史
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 二维平面内的碰撞检测【一】
  • 开源地图数据可视化库——mapnik
  • 力扣(LeetCode)357
  • 如何编写一个可升级的智能合约
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 用Python写一份独特的元宵节祝福
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​LeetCode解法汇总518. 零钱兑换 II
  • ​Python 3 新特性:类型注解
  • (1)无线电失控保护(二)
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (回溯) LeetCode 46. 全排列
  • (每日一问)设计模式:设计模式的原则与分类——如何提升代码质量?
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (三)docker:Dockerfile构建容器运行jar包
  • (十二)Flink Table API
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (转)h264中avc和flv数据的解析
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • ../depcomp: line 571: exec: g++: not found
  • ./和../以及/和~之间的区别
  • .FileZilla的使用和主动模式被动模式介绍
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .net FrameWork简介,数组,枚举
  • .NET Micro Framework初体验
  • .NET Project Open Day(2011.11.13)