Android SurfaceFlinger——服务启动流程(二)

        SurfaceFlinger 是 Android 系统中的一个核心服务,负责管理图形缓冲区的合成和屏幕显示,是 Android 图形系统的关键组件。

一、启动流程

        SurfaceFlinger 作为一个系统服务,在 Android 启动早期由 init 进程通过 servicemanager 启动。它是作为用户空间的一部分运行的,通常拥有 root 权限。在初始化阶段,SurfaceFlinger 通常还需要完成以下工作:

  • 设置其运行环境,包括创建必要的线程(如主线程、处理消息的线程等)、初始化硬件模块(如 GPU 驱动)、以及配置显示设备等。
  • 建立 DisplayHardware,SurfaceFlinger 会与硬件抽象层(HAL)交互,通过 HAL 与具体的显示硬件设备进行通信。这包括查询硬件支持的显示模式、分辨率、刷新率等信息,并根据系统配置选择合适的显示模式。
  • 创建 ComposerClient,在某些Android版本中,SurfaceFlinger 会通过HWC(Hardware Composer)与图形硬件直接交互。它会创建一个 ComposerClient 实例来管理硬件合成器,这个过程涉及与硬件加速器的初始化和设置。
  • 初始化 LayerManager,SurfaceFlinger 维护了一个 LayerManager,用于管理所有的 Surface(即图层层)。在初始化时,它会创建根 Layer,这个 Layer 代表整个屏幕,并为后续的窗口和 Surface 创建做准备。
  • 设置色彩管理,包括加载色彩配置文件,确保屏幕颜色准确无误地显示。
  • 建立与 SurfaceControl 的连接,SurfaceControl 是应用程序与 SurfaceFlinger 通信的接口。初始化时,SurfaceFlinger 会准备好接受来自应用程序的 Surface 创建、更新和销毁请求。
  • 事件监听与处理机制,设置 VSync(垂直同步)信号监听,确保每一帧的绘制都在最佳时间点进行,减少撕裂现象。同时,初始化事件处理机制,准备处理来自系统和其他服务的命令和事件。
  • 安全性设置,SurfaceFlinger 还会进行一些安全性方面的初始化,比如设置 SELinux 策略,确保其运行时的权限和访问控制符合系统安全要求。

        整个初始化过程确保了 SurfaceFlinger 能够准备好处理图形数据的接收、合成和显示,为 Android 应用的 UI 渲染提供基础服务。 

        要了解 SurfaceFlinger 的启动流程需要看看 SurfaceFlinger 对应模块目录下的 bp 文件。

1、Android.bp

源码位置:/frameworks/native/services/surfaceflinger/Android.bp

……
cc_defaults {name: "libsurfaceflinger_defaults",defaults: ["surfaceflinger_defaults","skia_renderengine_deps",],……shared_libs: [……"android.hardware.graphics.allocator@2.0","android.hardware.graphics.allocator@3.0",……"android.hardware.graphics.composer@2.1","android.hardware.graphics.composer@2.2","android.hardware.graphics.composer@2.3","android.hardware.graphics.composer@2.4","android.hardware.graphics.composer3-V1-ndk",……"libbinder","libbinder_ndk","libcutils","libEGL","libfmq","libGLESv1_CM","libGLESv2",……],……
}
……
filegroup {name: "libsurfaceflinger_sources",srcs: [// cpp源代码文件……],
}
……
filegroup {name: "surfaceflinger_binary_sources",srcs: [":libsurfaceflinger_sources","main_surfaceflinger.cpp",],
}cc_binary {name: "surfaceflinger",defaults: ["libsurfaceflinger_binary"],init_rc: ["surfaceflinger.rc"],srcs: [":surfaceflinger_binary_sources",// 注意:SurfaceFlingerFactory不在文件组中,因此可以很容易地替换它。"SurfaceFlingerFactory.cpp",],shared_libs: ["libSurfaceFlingerProp",],logtags: ["EventLog/EventLogTags.logtags"],
}
……

        这里我们可以看到几个核心的内容:

  • android.hardware.graphics.allocator@2.0:图形内存分配器抽象硬件层的实现。
  • android.hardware.graphics.composer@2.x:hwc 图层合成抽象硬件层实现。
  • binder、opengles、hwbinder(抽象硬件层的 binder)等。
  • 设定了SurfaceFlinger 的在 Android 启动初期需要加载的 init.rc 文件——surfaceflinger.rc。
  • SurfaceFlinger 的主函数入口 main_surfaceflinger.cpp。

        在了解了 SurfaceFlinger 模块的 bp 文件后,对于 SurfaceFlinger 的启动流程,我们知道该服务是通过解析 surfaceflinger.rc 进行启动的,并且服务的主函数入口在 main_surfaceflinger.cpp 中。

2、surfaceflinger.rc

源码位置:/frameworks/native/services/surfaceflinger/surfaceflinger.rc

service surfaceflinger /system/bin/surfaceflingerclass core animationuser systemgroup graphics drmrpc readproc// 允许调整进程优先级capabilities SYS_NICE// 如果surfaceflinger服务重启,且zygote服务正在运行,则同时重启zygote服务onrestart restart --only-if-running zygote// 指定服务的任务性能配置为HighPerformancetask_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:s0

         这里主要用于定义 surfaceflinger 服务的属性和权限设置,同时还启动了三个 socket,分别用于虚拟现实(VR)显示的客户端连接、管理端连接以及垂直同步(vsync)信号。配置确保了 surfaceflinger 服务能够在 Android 系统中安全高效地运行,处理图形显示和 VR 相关的功能。

3、main_surfaceflinger.cpp

源码位置:/frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp

int main(int, char**) {signal(SIGPIPE, SIG_IGN);// 初始化硬件相关的RPC线程池hardware::configureRpcThreadpool(1 /* maxThreads */, false /* callerWillJoin */);// 启动图形内存分配服务startGraphicsAllocatorService();// 将Binder线程池的最大线程数设置为4,适用于SurfaceFlinger独立进程场景。ProcessState::self()->setThreadPoolMaxThreadCount(4);……// 启动线程池sp<ProcessState> ps(ProcessState::self());ps->startThreadPool();……// 创建SurfaceFlinger对象sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();……// 提升当前进程的调度优先级setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);set_sched_policy(0, SP_FOREGROUND);// 根据是否启用CPU集,调整SurfaceFlinger相关线程的CPU使用策略,避免不必要的大核使用if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);// 初始化SurfaceFlinger,准备接收客户端连接。flinger->init();// 通过IServiceManager向系统服务管理器注册SurfaceFlinger及其AIDL接口。sp<IServiceManager> sm(defaultServiceManager());sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);sp<SurfaceComposerAIDL> composerAIDL = new SurfaceComposerAIDL(flinger);sm->addService(String16("SurfaceFlingerAIDL"), composerAIDL, false,IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);// 启动Display服务startDisplayService(); // 依赖于上面注册的SF// 确保SurfaceFlinger运行在SCHED_FIFO调度策略下if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {ALOGW("Couldn't set to SCHED_FIFO: %s", strerror(errno));}// 运行SurfaceFlinger,进入主循环,处理图形显示相关的任务。flinger->run();return 0;
}

        整个过程涉及了线程管理、资源分配、进程优先级调整等多个方面,确保 SurfaceFlinger 能够高效、稳定地提供图形显示服务。这里有如下几个核心方法:

  • startGraphicsAllocatorService:初始化 Hal 层的图元生成器服务。
  • 初始化 ProcessState,也就是把该进程映射到 Binder 驱动程序。
  • SurfaceFlinger 实例化。
  • set_sched_policy 设置为前台进程。
  • SurfaceFlinger 调用 init 方法。
  • 因为 SurfaceFlinger 本质上也是一个 Binder 服务,因此添加到 ServiceManager 进程中。
  • 初始化 GpuService,也添加到 ServiceManager 进程中。
  • 启动 DisplayService。
  • sched_setscheduler 把进程调度模式设置为实时进程的 FIFO。
  • 调用 SurfaceFlinger 的 run 方法。

二、总结

初始化阶段

        由 init 进程启动:SurfaceFlinger 服务作为 Android 系统中的一个关键服务,是由 init 进程根据 init.rc 配置文件启动的。在这个阶段,init 进程会 fork 出一个新的进程来运行 SurfaceFlinger 服务。

执行main函数

        main_surfaceflinger.cpp:SurfaceFlinger 的生命周期从其 C++ 主入口点 main() 函数开始。这个函数执行一系列初始化操作,包括但不限于:

  • 创建线程池:为了高效处理多任务,SurfaceFlinger 会创建一个线程池。
  • 设置进程和线程优先级:确保 SurfaceFlinger 具有合适的调度优先级以满足实时显示需求。
  • 初始化硬件模块:如 HWC(Hardware Composer)和 EGL(Embedded Graphics Library)等,这些对于图形渲染至关重要。
  • 创建 SurfaceFlinger 对象:这是服务的核心实例,负责管理显示和图层的合成。
  • Binder 初始化:SurfaceFlinger 服务会检查并准备 Binder 机制,这是 Android 系统中进程间通信(IPC)的关键部分。这允许其他应用和服务通过 Binder 接口与 SurfaceFlinger 交互。
  • ServiceManage r 注册:SurfaceFlinger 通过 Binder 向 ServiceManager 注册自己,使其对整个系统可用。这样,其他组件如 Window Manager 等可以发现并连接到 SurfaceFlinger 服务。
  • 启动线程和循环:初始化完成后,SurfaceFlinger 进入主事件循环,监听和处理来自客户端的请求,如创建新的 Surface,更新图层属性,以及执行实际的屏幕合成操作。

        综上所述,SurfaceFlinger 的启动是一个复杂但有序的过程,涉及了从底层硬件初始化到高层服务注册的一系列步骤,确保系统能够高效、稳定地进行图形显示。

流程图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/30631.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【黑马TS】学习资料Day4

五、在 React 中使用 TypeScript 现在&#xff0c;我们已经掌握了 TS 中基础类型、高级类型的使用了。但是&#xff0c;如果要在前端项目开发中使用 TS&#xff0c;还需要掌握 React、Vue、Angular 等这些库或框架中提供的 API 的类型&#xff0c;以及在 TS 中是如何使用的。 …

作为一名程序员,最大的成就感来自哪里?

说在前面 &#x1f388;作为一名程序员&#xff0c;我们的生活充满了挑战与创造。在成千上万行代码的背后&#xff0c;我们的成就感来源于何处&#xff1f;是解决问题的瞬间&#xff0c;是产品发布的一刻&#xff0c;还是用户的一声赞叹&#xff1f; 解决问题的瞬间 每当我们调…

AI写作平台:提升文档撰写效率的神器

工欲善其事&#xff0c;必先利其器。 随着AI技术与各个行业或细分场景的深度融合&#xff0c;日常工作可使用的AI工具呈现出井喷式发展的趋势&#xff0c;AI工具的类别也从最初的AI文本生成、AI绘画工具&#xff0c;逐渐扩展到AI思维导图工具、AI流程图工具、AI生成PPT工具、AI…

驱动层透明加密技术是什么?

驱动层透明加密技术的应用场景主要集中在确保数据在存储、传输和使用过程中的安全性&#xff0c;特别是在需要严格控制文件访问和防止数据泄露的场合。以下是几个具体的应用场景&#xff0c;结合参考文章中的相关信息进行归纳&#xff1a; www.weaem.com 内部文件流通&#xf…

【索引】数据库索引之顺序索引概述

目录 1、索引的基本概念 2、顺序索引 3、稠密索引和稀疏索引 3.1 什么是稠密索引&#xff1f; 3.2 什么是稀疏索引&#xff1f; 4、索引的更新 4.1 索引的插入操作 4.1 索引的删除操作 5、辅助索引 1、索引的基本概念 数据库中的索引与图书馆中书的索引作用相同&#xf…

Spire.PDF for .NET【文档操作】演示:如何删除 PDF 中的图层

借助Spire.PDF&#xff0c;我们可以在新建或现有pdf文档的任意页面中添加线条、图像、字符串、椭圆、矩形、饼图等多种图层。同时&#xff0c;它还支持我们从pdf文档中删除特定图层。 Spire.PDF for .NET 是一款独立 PDF 控件&#xff0c;用于 .NET 程序中创建、编辑和操作 PD…

【Python/Pytorch 】-- 滑动窗口算法

文章目录 文章目录 00 写在前面01 基于Python版本的滑动窗口代码02 算法效果 00 写在前面 写这个算法原因是&#xff1a;训练了一个时序网络&#xff0c;该网络模型的时序维度为32&#xff0c;而测试数据的时序维度为90。因此需要采用滑动窗口的方法&#xff0c;生成一系列32…

虚拟DOM的比较

patch 将虚拟DOM渲染成DOM&#xff0c;这就是patch的作用 在vue运行的时候会生成新旧两个虚拟DOM树&#xff0c;通过比较这两棵DOM树&#xff0c;我们就能针对性的修改真实DOM 事实上&#xff0c;我们大可以在每次比较两棵DOM树的时候删除现有的DOM结构&#xff0c;然后根据新的…

大数据-数据分析初步学习,待补充

参考视频&#xff1a;数据分析只需3小时从入门到进阶&#xff08;up亲身实践&#xff09;_哔哩哔哩_bilibili 数据指标&#xff1a; 对当前业务有参考价值的统计数据 分类&#xff1a;用户数据&#xff0c;业务数据&#xff0c;行为数据 用户数据 存量&#xff1a; DAU&#…

可信计算和数字水印技术

可信计算 可信计算可信计算基础概述可信计算关键技术要素可信性认证可信计算优劣 数字水印技术数字版权保护技术 可信计算 可信计算基础概述 可信计算&#xff08;Trusted Computing&#xff0c;TC&#xff09;&#xff1a;在计算和网络通信系统中广泛使用的、基于硬件安全模块…

Android Glide, first start based on loadThumbnail, Kotlin(二)

Android Glide, first start based on loadThumbnail, Kotlin&#xff08;二&#xff09; Android Glide, first start based on loadThumbnail, Kotlin&#xff08;一&#xff09;中有个小问题&#xff0c;通过loadThumbnail()采集到的缩略图真的就是整张图片的完整缩略图&…

C语言入门系列:数据类型之布尔类型

文章目录 1&#xff0c;以前&#xff0c;C语言没有布尔类型2&#xff0c;后来&#xff0c;C语言假装有了布尔类型3&#xff0c;再后来&#xff0c;C语言的非标布尔类型 1&#xff0c;以前&#xff0c;C语言没有布尔类型 其实&#xff0c;C 语言没有真正的布尔类型&#xff0c;…

STM32通过I2C软件读写MPU6050

文章目录​​​​​​​ 1. MPU6050 1.1 运动学概念 1.2 工作原理 2. 参数 2.1 量程选择 2.2 I2C从机地址配置 3. 硬件电路 4. 框架图 5. 软件和硬件波形对比 6. 软件I2C读写MPU6050 6.1 程序整体构架 6.2 一些需要注意的点&#xff1a; 6.3 MPU6050初始化配置 6…

支持 MKV、MP4、AVI、MPG 等格式视频转码器

一、简介 1、一款开源的视频转码器&#xff0c;适用于 Linux、Mac 和 Windows。它是一个免费的工具&#xff0c;由志愿者们开发&#xff0c;可以将几乎所有格式的视频转换为现代、广泛支持的编码格式。你可以在官网上下载该应用或源代码。该软件支持 MKV、MP4、AVI、MPG 等格式…

如何计算文档会消耗的Token数量?

在AI的世界里&#xff0c;"token"就像是把我们说的话或写的文字拆分成的小块块&#xff0c;每块可以是一个词、一个短语、一个标点&#xff0c;甚至一个字母。不同的AI系统可能有不同的拆分方法。 阿里云的灵积平台有个工具&#xff0c;叫做Token计算器。这个工具就…

经常混淆的ADC输入类型!

大家好,这里是大话硬件。 这篇文章我们来聊聊ADC的输入类型。 ADC的输入类型根据ADI的官网,分为了3种类型,单端,差分,伪差分。如下图快速选型的界面所示。 同时,TI的官网对ADC的输入类型划分也是同样的3种类型。 可见,两个器件厂家对ADC的输入类型都是这样定义的。 …

springMVC的bug

写SpringMVC时&#xff0c;配置视图解析器路径中少写了个“/”导致url拼接错误&#xff0c;无法返回视图

支持向量机 (SVM) 算法详解

支持向量机 (SVM) 算法详解 支持向量机&#xff08;Support Vector Machine, SVM&#xff09;是一种监督学习模型&#xff0c;广泛应用于分类和回归分析。SVM 特别适合高维数据&#xff0c;并且在处理复杂非线性数据时表现出色。本文将详细讲解 SVM 的原理、数学公式、应用场景…

项目中选择Entity Framework Core还是Dapper?

我是将 Dapper 还是 Entity framework core 用于下一个 .NET 项目&#xff1f;当你必须做出这个决定时&#xff0c;总是令人困惑&#xff0c;为了项目的成功&#xff0c;你需要做出正确的决定。让我来帮你... 介绍 使用 .NET 开发的应用程序可以根据其使用的对象关系映射器 &…

Java | Leetcode Java题解之第168题Excel表列名称

题目&#xff1a; 题解&#xff1a; class Solution {public String convertToTitle(int columnNumber) {StringBuffer sb new StringBuffer();while (columnNumber ! 0) {columnNumber--;sb.append((char)(columnNumber % 26 A));columnNumber / 26;}return sb.reverse().t…