Android SurfaceFlinger——概述(一)

一、基础介绍

        SurfaceFlinger 是 Android 系统中的一个关键组件,负责管理屏幕显示的合成和渲染。

  • 服务角色:SurfaceFlinger 作为一个系统服务独立运行,它不依赖于任何应用程序进程,而是由系统启动并持续运行。
  • 窗口管理:它管理着系统中所有窗口的层次结构,包括应用程序窗口、状态栏、导航栏等,并根据ZOrder(深度顺序)决定哪些窗口应该在前面显示。
  • 合成操作:SurfaceFlinger 接收各个窗口的 Surface(图形缓冲区),这些 Surface 可能来自不同的应用程序或系统服务。根据每个 Surface 的透明度、大小、位置等属性,SurfaceFlinger 计算它们在最终显示图像中的位置和效果。
  • 硬件加速:SurfaceFlinger 利用硬件加速功能,如 GPU,来高效地执行合成操作。它可以与 HWComposer(硬件作曲家)协同工作,优化显示性能和功耗。
  • 帧缓冲区操作:合成后的图像被写入到帧缓冲区,然后由显示硬件读取并呈现到屏幕上。
  • 多显示器支持:SurfaceFlinger 还支持多显示器配置,能够将内容正确地输出到连接到设备的多个显示设备上。
  • 低延迟渲染:为了实现流畅的用户体验,SurfaceFlinger 致力于减少帧之间的延迟,确保以 60Hz 或其他刷新率连续显示内容。
  • 与其他组件的交互:与 WMS(Window Manager Service)协作,处理窗口的布局和可见性。与 Content Providers、View System 等其他 Android 组件进行通信,获取和更新显示内容。
  • 权限控制:SurfaceFlinger 还负责权限控制,确保只有授权的进程可以访问和修改显示内容。

        通过上述功能,SurfaceFlinger 在 Android 系统中扮演着至关重要的角色,确保了用户界面的正确显示和高效的渲染。

二、系统渲染流程

1、SurfaceFlinger

        SurfaceFlinger 是整个 Android 系统渲染的核心进程。所有应用的渲染逻辑最终都会来到 SurfaceFlinger 中进行处理,最终会把处理后的图像数据交给 CPU 或者 GPU 进行绘制。

        在这个过程中 SurfaceFlinger 并非担当渲染的角色,而是作为图元抛射机一样,把所有应用进程传递过来的图元数据加工处理后,交给 CPU 和 GPU 做真正的绘制。

2、Surface

        在每一个应用中都以 Surface 作为一个图元传递单元,向 SurfaceFlinger 这个服务端传递图元数据。

        Surface 与 SurfaceFlinger 交互流程如下图所示:

3、设计思想

        SurfaceFlinger 是以生产者以及消费者为核心设计思想,把每一个应用进程作为生产者生产图元保存到 SurfaceFlinger 的图元队列中,SurfaceFlinger 则作为消费者依照一定的规则把生产者存放到 SurfaceFlinger 中的队列一一处理。

        SurfaceFlinger 处理 Surface 流程如下:

4、共享内存

        为了能够跨进程的传输大容量的图元数据,使用了匿名共享内存内存作为工具把图元数据都输送到 SurfaceFlinger 中处理。

        我们要知道从应用进程把图元数据传输到 SurfaceFlinger 进程中处理,就需要跨进程通信,这里我们能想到的就是 socket通信、Binder 通信以及共享内存了。对于 Ashmem 匿名共享内存的选择,后面我们详细讲解。

5、时间钟

        SurfaceFlinger 底层有一个时间钟在不断的循环,或从硬件中断发出,或从软件模拟发出计时唤起,每隔一段时间都会获取 SurfaceFlinger 中的图元队列通过 CPU/GPU 绘制在屏幕。

        这个时间钟很符合 Android 系统的设计情况,除了需要 Android 应用有办法通知 SurfaceFlinger 需要渲染的模式,也需要 SurfaceFlinger 在不断的处理图元数据并绘制到屏幕的同时回调信息给自身。

        其中 EventThread 扮演一个极其重要的角色,在 SurfaceFlinger 中设计大致如下:

三、缓冲原理

        在了解缓冲原理前,我们先来开一个比较重要的概念——垂直同步信号(VSync)。

1、垂直同步信号

        在 SurfaceFlinger 中,垂直同步信号(Vertical Synchronization, VSync)起着核心作用,确保图形渲染和屏幕显示的同步,避免画面撕裂现象并提高视觉流畅性。

  • 作用原理:VSync 是一种同步机制,与显示器的刷新周期对齐,指示何时开始新的一帧渲染最合适。每当显示器完成一次刷新周期,硬件会产生一个 VSync 信号,通知系统现在可以安全地开始绘制下一帧图像。
  • 硬件与软件的结合:虽然早期的 SurfaceFlinger 可能依赖于软件模拟 VSync,现代 Android 系统通常利用硬件提供的精确 VSync 信号,以减少误差和提升效率。
  • 分发与接收:SurfaceFlinger 负责接收硬件产生的 VSync 信号,并将其分发给系统中的渲染器,包括 App 的 UI 线程和 SurfaceFlinger 自身。onVSyncReceived 方法会在接收到 VSync 信号时被调用,该方法内部会触发一系列的渲染调度操作。
  • 同步渲染:应用程序通过 Choreographer(编舞者)类监听 VSync 信号,确保 UI 绘制与屏幕刷新同步。这使得 AppUI 和 SurfaceFlinger 都能按照硬件 VSync 的节奏进行工作,从而保证动画和滚动等操作的平滑性。
  • 减少延迟与提高效率:通过精确的 VSync 同步,可以减少由于无序渲染导致的额外缓冲需求,降低输入到显示的延迟。VSync 还帮助优化 CPU 和 GPU 的利用率,避免过度渲染或空闲等待,进而节省电池。
  • 可调节性:在某些场景下,开发者可以通过调整 Choreographer 的行为来适应特定的渲染需求,比如三重缓冲策略的调整。
  • 异常处理与校准:SurfaceFlinger 还涉及处理 VSync 信号的异常情况,比如信号丢失或频率不匹配,以维持系统的稳定性和显示质量。

        综上所述,VSync 在 SurfaceFlinger 中是确保图形显示流畅和高效的基石,通过精确的时间控制,协调系统资源,提供最佳的用户体验。

2、双缓冲

        在 SurfaceFlinger 中,双缓冲是一种优化显示性能的技术,用于减少屏幕闪烁并提高动画的平滑性。

  • 缓冲区管理:双缓冲涉及到两个独立的帧缓冲区(front buffer 和 back buffer)。前缓冲区是当前显示在屏幕上的图像,而后缓冲区则用于绘制新的内容。
  • 绘制过程:应用程序在后台缓冲区完成绘制操作,不会影响到正在显示的图像。当绘制完成后,SurfaceFlinger 会收到 VSync 信号,此时可以安全地交换前后缓冲区。
  • 缓冲区交换:在 VSync 时刻,SurfaceFlinger 将后缓冲区的内容复制到前缓冲区,这个过程称为"翻页"或"PageFlip"。这个操作通常是原子性的,确保在屏幕刷新时看到的是完整的一帧,而不是部分更新的内容。
  • 减少闪烁:因为用户看到的始终是已经完成绘制的图像,而不是正在绘制的过程,所以避免了因多次绘制导致的闪烁现象。
  • 提高效率:应用程序可以同时在后缓冲区进行下一帧的绘制,而前一帧的显示不会受到影响,这提高了渲染效率。

        简单来说,双缓冲就是渲染第一帧的同时已经在绘制第二帧的内容,等到第二帧绘制完毕后就显示出来。这么做的好处很明显,如果一帧画完,才开始画下一帧,势必有一个计算的过程导致 ui 交互迟缓。 

        双缓冲是 SurfaceFlinger 在处理多个窗口和动画时的关键技术,它确保了 Android 系统的视觉流畅性和稳定性。通过与 VSync 信号的配合,双缓冲有效地减少了画面撕裂和不连续的视觉效果,提升了用户体验。 

        通过这种方式显示前一帧的时候提前绘制好下一帧图元,放在背后等待时机交换,这样就能从感官上流畅不少。

        这么做的效果十分显示,但是怎么找到一个合适的时机进行交换前后两帧这是一个问题,如果按照屏幕刷新频率来,一般按照通用屏幕刷新 60fps 也就是约 16ms 刷新一次即可。但是我们深入思考一下,其实这个过程中有两个变量,一个是绘图速度,一个是显示速度。就算是绘图速度中也有分 CPU 和 GPU 的绘制速度。

        这里我看一下当年 google 在“黄油计划”示意图。

无缓冲流程

        理想中的情况就是上图,在显示第 0 帧的时候,CPU/GPU 合成绘制完成第 1 帧在 16ms 内,当 vsync 信号来了,就把第 1 帧交换到显示屏显示。

        但是很可能出现下面这种情况,CPU 因为繁忙来不及,显示完第一帧的时候,还没空渲染第二帧,就算 SurfaceFlinger 接受到了 Vsync 的信号,也只能拿出已经渲染好的第一帧显示在屏幕上。这样就重复显示了第一帧,Google 开发团队称这种为 jank。

        能看到显示第一帧因为第二帧没准备好,只能重复显示第一帧了。再来看看双缓冲的工作原理流程。

双缓冲流程

        可以看到此时就不是简单的第一第二帧,而是分为 A 缓冲,B 缓冲。能看到在正常情况下,先显示 A 缓冲的内容,同时准备B缓冲,当一切正常的时候,B 缓冲应该在下一个 vsync 来之前准备好,一旦 vsync 到来则显示 B 缓冲,A 缓冲回到后台继续绘制。

        那么这种方式一旦遇到 jank 会是什么样的一个情况。

        如果是双缓冲好像没有问题,但是一旦出现 jank 了之后,之后显示屏就会不断的出现 jank。如果缓冲 A 在显示,而 B 准备的时间超过 16ms,就会导致 A 缓冲区重复显示,而当 B 显示的时候,A 也很可能准备时间不足 16ms 导致无法绘制完成,只能重复显示 B 缓冲的内容。

        这种方式更加的危险,为了解决这个问题,Google 引入三重缓冲。

3、三重缓冲

        在 SurfaceFlinger 中,三重缓冲(Triple Buffering)是双缓冲的一个扩展,旨在进一步减少画面撕裂和提高渲染性能,特别是在高帧率和垂直同步(V-Sync)启用时。

  • 缓冲区数量:与双缓冲的两个缓冲区不同,三重缓冲使用三个独立的帧缓冲区。当前显示的前缓冲区、一个用于绘制的新缓冲区(后缓冲区)以及一个额外的中间缓冲区。
  • 渲染流程:应用程序在中间缓冲区完成新帧的渲染,同时前缓冲区正在屏幕上显示。当前帧绘制完成后,SurfaceFlinger 等待下一个 VSync 信号,然后将中间缓冲区的内容移动到后缓冲区。
  • 缓冲区交换:在下一个 VSync 到来时,SurfaceFlinger 将后缓冲区的内容复制到前缓冲区,同时释放中间缓冲区供应用程序绘制下一帧。
  • 这样,应用程序可以在前一帧显示的同时开始绘制下一帧,而不是等待前一帧完全呈现后再开始。
  • 减少延迟:三重缓冲减少了等待 VSync 信号的空闲时间,因为总有一个缓冲区可供应用程序使用,从而降低了帧间延迟。
  • 性能提升:在某些情况下,尤其是在高帧率下,三重缓冲可以减少因等待 VSync 而引起的帧率下降,从而提供更稳定的帧率表现。
  • 权衡:尽管三重缓冲可以提高性能,但它也增加了内存占用,因为需要存储额外的缓冲区。此外,对于某些设备或应用场景,双缓冲可能已经足够,而且更节省资源。
  • 适用场景:三重缓冲通常在需要高性能图形渲染、高刷新率显示器或者需要减少 V-Sync 带来的延迟时采用。

        三重缓冲是 SurfaceFlinger 为了优化高动态场景和减少延迟而采用的一种策略,它在现代游戏和高性能应用中尤其有用,能够提供更加流畅的视觉体验。

        三重缓冲处理 jank 的原理流程图:

        可以看到为了避免后面连锁式的错误,引入三重缓冲就为了让空闲出来的等待时间,能够做更多的事情。就如同双缓冲遇到 jank 之后,一旦 B 缓冲 CPU+GPU 的时间超过了下一个 vsync 的时间,能够发现其实 CPU 和 GPU 有一段时间都没有事情做,光等待下一次 Vsync 的到来,才会导致整个系统后面的绘制出现连锁式的出现 jank。

        而三缓冲的出现,在重复显示 A 缓冲区的时候,CPU 不会光等待而是会准备 C 缓冲区的图元,之后就能把 C 缓冲区接上。这就是 Google 所说的三重缓冲区的来源,不过绝大多数情况下的缓冲策略都是由 SurfaceFlinger 系统自己决定的。实际上这种方式也可以用到音视频的编写优化,里面常用的缓冲区设计和这里也有异曲同工之处。

        有了缓冲原理的介绍,这里我们再来回顾一下上面的时间钟。其实每一次 Vsync 从硬件/软件过来的时候,Dispsync 都会尝试着通知 SurfaceFlinger 和APP,这是完全没有问题,而后面那个 Phase 相位又有什么作用?这就是系统的设计的巧妙,我们如果同时把信号通知同时告诉 APP 和 SurfaceFlinger 会导致什么结果?

        如果此时 APP 后返回了图元,但是 SurfaceFlinger 已经执行了刷新合成绘制行为(很有可能,因为 APP 到 SurfaceFlinger 传输图元速度必定比 SurfaceFlinger 自己通知自己慢),此时就会导致类似 jank 的问题,导致下一个 vsync 还是显示当前帧数,因此需要如下一个时间差,先通知 APP 后通知 SurfaceFlinger,如下图:

        加上这个理解就能明白上面 Phase 相位处理的初衷了。

总结

        对于系统渲染流程的理解是指导 SurfaceFlinger 设计的核心思想,从 Android 4.1 一直到 Android 9.0 都没有太大的变化。只要抓住这五个核心思想,我们阅读 SurfaceFlinger 的难度就会下降不少。

        下面看一下 SurfaceFlinger 的体系和 Skia 以及 View的绘制流程的关系。

  • framework 面向开发者所有的 View 是便于开发的控件,里面仅仅只是提供了当前 View 各种属性以及功能。
  • 而 Android 底层的 Skia 是 Android 对于屏幕上的画笔,经过 View 绘制流程的 onDraw 方法回调,把需要绘制的东西通过 Skia 绘制成像素图元保存起来
  • SurfaceFlinger 则是最后接受 Skia 的绘制结果,最后绘制到屏幕上。

        所以说,Skia 是 Android 渲染核心,但是最终还是需要 Skia 和系统所提供起来,才是一个 Android 完整渲染体系。经过这一层层的屏蔽,让开发者不需要对 Android 底层的渲染体系有任何理解,也能绘制出不错的效果。

        最后会把绘制结果传输到屏幕中。

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

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

相关文章

用Flask定制指令上传Excel数据到数据库

用Flask定制指令上传Excel数据到数据库 假设现在有一张员工信息data.xlsx文件 使用SQLAlchemy创表 # ExcelModel.py from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.orm import DeclarativeBaseclass Base(DeclarativeBase):passclass Emp(…

《Windows API每日一练》4.6 矩形、区域和裁剪

在前面的4.3节中我们讲述了绘制矩形的API函数Rectangle和RoundRect。本节我们将介绍另外一组使用RECT矩形结构和区域的绘图函数。 本节必须掌握的知识点: 矩形 第28练:绘制随机矩形 矩形与区域的裁剪 第29练:区域裁剪 4.6.1 矩形 ■FillRe…

2025年计算机毕业设计题目参考-简单容易

2025年最新计算机毕业设计题目参考-第二批 以下可以参考 企业员工薪酬关系系统的设计 基于SpringBoot在线远程考试系统 SpringBootVue的乡政府管理系统 springboot青年公寓服务平台 springboot大学生就业需求分析系统 基于Spring Boot的疗养院管理系统 基于SpringBoot的房屋交…

堆优化版Dijkstra求最短路-java

主要通过堆优化Dijkstra算法解决最短路,可以跟朴素版的Dijkstra算法进行对比。 文章目录 前言 一、Dijkstra求最短路 二、算法思路 1.邻接表存储图 2.用小根堆优化Dijkstra 三、代码如下 1.代码如下(示例): 2.读入数据 3.代码运行…

高压线防外破警示灯在电力安全发挥的作用_鼎跃安全

高压输电线路往往跨越城市、乡村和野外,覆盖范围广泛。随着城乡建设和交通运输的快速发展,高压线路周围的活动频繁,外部破坏风险增加。车辆撞击电线杆、施工机械误碰线路以及人为破坏等事件时有发生,严重影响电力供应的稳定性和安…

人工智能--自然语言处理NLP概述

欢迎来到 Papicatch的博客 目录 🍉引言 🍈基本概念 🍈核心技术 🍈常用模型和方法 🍈应用领域 🍈挑战和未来发展 🍉案例分析 🍈机器翻译中的BERT模型 🍈情感分析在…

深入了解Java的ConcurrentHashMap类

深入了解Java的ConcurrentHashMap类 在多线程编程中,线程安全的数据结构至关重要。ConcurrentHashMap是Java提供的一种线程安全的哈希表实现,它在不使用显式同步的情况下允许并发的读取和写入操作。 ConcurrentHashMap属于java.util.concurrent包。它是…

19.Docker跨宿主机容器之间的通信macvlan

Docker跨宿主机容器之间的通信macvlan,类似桥接网络模式 macvlan通信类型,设置IP地址只能手动指定(–ip)一台一台设置IP地址 默认一个物理网卡,只有一个物理mac地址,虚拟多个mac地址(让人感觉是…

【机器学习】第7章 集成学习(小重点,混之前章节出题但小题)

一、概念 1.集成学习,顾名思义,不是一个玩意,而是一堆玩意混合到一块。 (1)基本思想是先 生成一定数量基学习器,再采用集成策略 将这堆基学习器的预测结果组合起来,从而形成最终结论。 &#x…

C# 利用XejeN框架源码,编写一个在 Winform 界面上的语法高亮的编辑器,使用 Monaco 编辑器

析锦基于Monaco技术实现的Winform语法高亮编辑器 winform中,我们有时需要高亮显示基于某种语言的语法编辑器。 目前比较强大且UI现代化的,无疑是宇宙最强IDE的兄弟:VS Code。 类似 VS Code 的体验,可以考虑使用 Monaco Editor&a…

【机器学习】第6章 支持向量机(SVM)

一、概念 1.支持向量机(support vector machine,SVM): (1)基于统计学理论的监督学习方法,但不属于生成式模型,而是判别式模型。 (2)支持向量机在各个领域内的…

【系统架构设计师】三、数据库系统(事务并发|封锁协议|数据库安全|商业智能|SQL语句)

目录 一、事务并发 1.1 事务概述 1.2 并发控制 1.3 封锁 1.3.1 X 封锁和 S 封锁 1.3.2 三级封锁协议 二、数据库安全 2.1 备份(转储)与恢复 2.2 备份分类 2.3 数据库故障 三、商业智能 3.1 数据仓库 3.2 数据仓库的结构-OLAP 3.3 数据挖掘 3.4 分布式数据库 四…

DS1302实时时钟芯片完整使用介绍(配合51单片机)

DS1302是一款由美国DALLAS Semiconductor公司(现已被Maxim Integrated公司收购)设计的高性能、低功耗的实时时钟集成电路。这款芯片因其简单易用的接口和丰富的功能,在嵌入式系统、消费电子、工业控制等多个领域得到广泛应用。 原理图 寄存器…

Vscode中的行尾序列CRLF/LF不兼容问题

最近开发的的时候,打开项目文件经常会出现爆红错误提示信息,显示如下图: 这东西太烦人了,毕竟谁都不希望在遍地都是爆红的代码里写东西,就像能解决这个问题,根据提示可以知道这是vscode中使用的prettier插件…

QT基础 - 布局管理器间隔控件

目录 一. QVBoxLayout 二. QHBoxLayout 三. QGridLayout 四. QFormLayout 五. Spacers 六.总结 一. QVBoxLayout QVBoxLayout 主要用于将控件在垂直方向上进行排列。 它具有以下特点: 可以方便地管理和组织控件,使其按照垂直顺序依次排列。能够自动…

数据治理平台报Invalid CORS request

文章目录 背景一、步骤1.修改治理conf配置文件 背景 问题描述:俩个域名(都能进入同一个平台)其中一个正常使用,另外一个无法进入 报错截图: *备注:本文主要从配置文件入手解决。 一、步骤 1.修改治理co…

无需付费,没有广告,驱动人生海外版本DriverTalent_Pro_v8.0.0.2单文件

如果你是一位电脑爱好者,你一定知道驱动程序的重要性。驱动程序是连接电脑硬件和操作系统的桥梁,它们可以让你的电脑运行更流畅,更稳定,更高效。但是,驱动程序也会随着时间的推移而过时,或者与新的系统不兼…

HTTP/3 协议学习

前一篇: HTTP/2 协议学习-CSDN博客 HTTP/3 协议介绍 HTTP/3 是互联网上用于传输超文本的协议 HTTP 的第三个主要版本。它是 HTTP/2 的后继者,旨在进一步提高网络性能和安全性。HTTP/3 与前两个版本的主要区别在于它使用了一个完全不同的底层传输协议—…

【linux】TCP交流状态变迁及一些函数调用

代码 登录 - Gitee.comhttps://gitee.com/r77683962/linux-6.9.0/commit/50bb00d844b9423c9bacf44d9b06604fab941686 https://gitee.com/r77683962/linux-6.9.0/raw/50bb00d844b9423c9bacf44d9b06604fab941686/dmesg_log/kern_tcp_with_state.log 从打印的日志,…

UE4中性能优化和检测工具

UE4中性能优化和检测工具合集 简述CPUUnreal InsightUnreal ProfilerSimpleperfAndroid StudioPerfettoXCode TimeprofilerBest Practice GPUAdreno GPUMali GPUAndroid GPU Inspector (AGI) 内存堆内存分析Android StudioLoliProfilerUE5 Memory InsightsUnity Mono 内存Memre…