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/surfaceflinger
    class core animation
    user system
    group graphics drmrpc readproc
    // 允许调整进程优先级
    capabilities SYS_NICE
    // 如果surfaceflinger服务重启,且zygote服务正在运行,则同时重启zygote服务
    onrestart restart --only-if-running zygote
    // 指定服务的任务性能配置为HighPerformance
    task_profiles HighPerformance
    socket pdx/system/vr/display/client     stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
    socket pdx/system/vr/display/manager    stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
    socket 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 的启动是一个复杂但有序的过程,涉及了从底层硬件初始化到高层服务注册的一系列步骤,确保系统能够高效、稳定地进行图形显示。

流程图

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【漏洞复现】用友 NC NCFindWeb 任意文件读取漏洞

免责声明&#xff1a; 本文内容旨在提供有关特定漏洞或安全漏洞的信息&#xff0c;以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步&#xff0c;并非出于任何恶意目的。阅读者应该明白&#xff0c;在利用本文提到的漏洞信息或进行相关测…

数学建模基础:统计模型

目录 前言 一、概率与统计基础 二、统计模型 三、Matlab统计工具箱 四、实例示范&#xff1a;市场调查分析 步骤 1&#xff1a;数据导入 步骤 2&#xff1a;数据可视化 步骤 3&#xff1a;建立多元线性回归模型 步骤 4&#xff1a;模型验证 步骤 5&#xff1a;模型应…

开发人员不要嗨,B端系统颜值不过关,可能进不去客户选择范围。

市面上形形色色的B端管理系统非常多&#xff0c;大家近身搏杀&#xff0c;这个市场已经成为了红海。也就是随便某一个功能领域&#xff0c;都有N的系统可以选择&#xff0c;这个时候你坚持B端系统功能使用就行&#xff0c;那就是自嗨了。现在是个过剩的时代&#xff0c;不是供不…

MaxWell实时监控Mysql并把数据写入到Kafka主题中

配置mysql 启用MySQL Binlog MySQL服务器的Binlog默认是未开启的&#xff0c;如需进行同步&#xff0c;需要先进行开启 修改MySQL配置文件/etc/my.cnf sudo vim/etc/my.cof 增加如下配置 注&#xff1a;MySQL Binlog模式 Statement-based&#xff1a;基于语句&#xff0c;…

数据分析第十二讲 数据可视化入门(一)

数据可视化入门&#xff08;一&#xff09; 在完成了对数据的透视之后&#xff0c;我们可以将数据透视的结果通过可视化的方式呈现出来&#xff0c;简单的说&#xff0c;就是将数据变成漂亮的统计图表&#xff0c;因为人类对颜色和形状会更加敏感&#xff0c;然后再进一步解读…

三步问题00

题目链接 三步问题 题目描述 注意点 n范围在[1, 1000000]之间结果可能很大&#xff0c;需要对结果模1000000007 解答思路 动态规划的思想根据dp[i - 1]、dp[i - 2]、dp[i - 3]推出dp[i]需要注意的是结果可能很大&#xff0c;在计算的过程中需要模1000000007防止越界 代码…

宋仕强论道之华强北假货之四

宋仕强论道之华强北假货之四&#xff0c;华强北虚标货。在华强北顾名思义就是“以少充多、以小充大&#xff0c;把低级当高级卖”。同样品牌和型号的产品&#xff0c;用民用级冒充工业级&#xff0c;工业级当军用级&#xff0c;军用级再当航天级&#xff0c;品牌型号都不变&…

全面升级,票据识别新纪元:合合信息TextIn多票识别2.0

票据识别 - 自动化业务的守门员 发票、票据识别&#xff0c;是OCR技术和RPA、CMS系统结合的一个典型场景&#xff0c;从覆盖率、覆盖面的角度来说&#xff0c;应该也是结合得最成功的场景之一。 产品简介 国内通用票据识别V2.0&#xff08;简称“多票识别2.0”&#xff09;是…

深入探讨:UART与USART在单片机中串口的实际应用与实现技巧

单片机&#xff08;Microcontroller Unit, MCU&#xff09;是一种集成了处理器、存储器和输入输出接口的微型计算机。它广泛应用于嵌入式系统中&#xff0c;用于控制各类电子设备。UART和USART是单片机中常见的通信接口&#xff0c;负责串行数据传输。下面我们详细介绍它们在单…

初阶 《数组》 1. 一维数组的创建和初始化

1. 一维数组的创建和初始化 1.1 数组的创建 数组是一组相同类型元素的集合 数组的创建方式&#xff1a; type_t arr_name [const_n]; //type_t 是指数组的元素类型 //const_n 是一个常量表达式&#xff0c;用来指定数组的大小数组创建的实例&#xff1a; //代码1 int ar…

手写月课表

农历插件&#xff1a;chinese-lunar-calendar - npm&#xff0c;这个插件可以计算农历日期和节气等 安装&#xff1a; npm install --save chinese-lunar-calendar 使用&#xff1a; import { getLunar } from chinese-lunar-calendar;let res getLunar(years, months, da…

【Linux基础IO】重定向以及原理分析

我们先来看下面一个情况&#xff1a; #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define filename "text.txt"int main(){close(1);//关…

人工智能在【妇科肿瘤】领域的最新进展|顶刊速递·24-06-20

小罗碎碎念 文献主题&#xff1a;人工智能在妇科肿瘤中的最新研究进展 如下图所示&#xff0c;今天的六篇推文中&#xff0c;研究的全部都是妇科疾病&#xff0c;包括&#xff1a; 乳腺癌宫颈癌卵巢癌子宫内膜癌 老板经常对我说&#xff0c;不要只关注自己的研究领域&#xff…

Python | Leetcode Python题解之第167题两数之和II-输入有序数组

题目&#xff1a; 题解&#xff1a; class Solution:def twoSum(self, numbers: List[int], target: int) -> List[int]:low, high 0, len(numbers) - 1while low < high:total numbers[low] numbers[high]if total target:return [low 1, high 1]elif total <…

ml307A模块连接阿里云(详细版)

1、需要的信息 MQTT连接参数、订阅或发布的主题、服务器地址、端口1883 服务器地址&#xff1a; alFMz7jnArW.iot-as-mqtt.cn-shanghai.aliyuncs.com 注&#xff1a;重要的信息阿里云信息大家不要透露&#xff0c;写完笔记会及时删除产品及设备&#xff0c;大家用自己的信息…

(7)摄像机和云台

文章目录 前言 1 云台 2 带有MAVLink接口的摄像机 3 相机控制和地理标签 4 视频质量差的常见修复方法 5 详细主题 前言 Copter、Plane 和 Rover 最多支持 3 轴云台&#xff0c;包括自动瞄准感兴趣区域&#xff08;ROI&#xff09;的相机和自动触发相机快门等先进功能。按…

C#开发-集合使用和技巧(七)分组方法GroupBy的使用

介绍 GroupBy 是 C# 中的一个 LINQ 扩展方法&#xff0c;用于根据指定的键将序列中的元素分组。它可以根据提供的键函数将数据分割成多个组&#xff0c;每组包含具有相同键的元素。 GroupBy也是一个在集合用比较常用的方法&#xff0c;也是比较好用的&#xff0c;适用于对序列…

前端技术栈二(promise模块化编程)

一、promise 1 Promise 基本介绍 传统的 Ajax 异步调用在需要多个操作的时候&#xff0c;会导致多个回调函数嵌套&#xff0c;导致代码不够直观&#xff0c;就是常说的 Callback Hell 为了解决上述的问题&#xff0c;Promise 对象应运而生&#xff0c;在 EMCAScript 2015 当中…

【MySQL连接器(Python)指南】02-MySQL连接器(Python)版本与实现

文章目录 前言MySQL连接器(Python)版本MySQL连接器(Python)实现总结前言 MySQL连接器(Python),用于让Python程序能够访问MySQL数据库。要想让Python应用程序正确高效地使用MySQL数据,就需要深入了解MySQL连接器的特性和使用方法。 MySQL连接器(Python)版本 下表总结了可用的…

java 不可变集合的创建和Stream流的使用

文章目录 一、创建不可变的集合1.1为什么创建不可变的集合1.2 创建List、Set和Map的不可变集合1.2.1 创建List的不可变集合1.2.2 创建Set 的不可变集合1.2.3 创建Map的不可变集合 二、使用集合 的Stream 流2.1 Stream的使用步骤2.2 Stream的方法 三、如何获取Stream 流对象四、…