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

Android图形显示流程简介

注:本文缩写说明

0a53a9984335dfbd97f28974d07ba4a8.png

本文代码都是基于Android S

一、概述

本文将对从App画出一帧画面到这帧画面是如何到达屏幕并最终被人眼看到的这一过程进行简要分析,并将这其中涉及到的各个流程与其在systrace上的体现对应起来,期望最终能够让读者对Android系统下的画面显示流程有一个宏观的认识。

1e7d9b2e14ec12d6a3c43a0e49884182.png

上图为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之间来回流转,本文将通过buffer的数据流向来详细阐述Android的画面显示过程。

二、App到SF

应用界面发生变化也就是view数据发生了变化,会引起ViewRootImpl的requestLayout调用,进而调用scheduleTraversals方法。scheduleTraversals方法内会先向消息队列发送一个同步屏障,然后执行Choreographer回调,注册CALLBACK_TRAVERSAL类型的监听。Choreographer在监听到下一次Vsync信号来了后,会执行mTraversalRunnable的run方法,该方法内会调用doTraversal方法,移除消息队列中的同步屏障,并通过performTraversals方法触发布局绘制流程。

dbe988c6080d5fab9c62798e1b800c79.png

Choreographer和Vsync是在Android 4.1上黄油计划中引入的两个重要元素,最初的Vsync信号是由硬件屏幕根据系统帧率以固定的频率(60/90/120fps)向系统发送的时间脉冲信号,Choreographer和SurfaceFlinger都会监听这个信号来做绘制和合成。后来为了进一步提升界面流畅性体验,Android 4.4上又引入了Vsync虚拟化,通过DispSyncThread把Vsync虚拟化成Vsync-app和Vsync-sf,Vsync-app和Vsync-sf之间有固定的时间偏移,各自分别掌控着App和SurfaceFlinger的工作节奏,他们一前一后保持着绘制任务的流水节奏。

当Choreographer监听到Vsync信号后会回调doFrame方法,该方法主要完成两件事情:确认当前帧执行的时间戳和渲染当前帧数据。渲染数据时会顺序执行输入(Input)、动画(Animation)、绘制(TRAVERSAL)、提交(Commit)这4种类型的回调函数,而在执行TRAVERSAL类型的callback方法时就会调用到上面提到的doTraversal下的performTraversals方法触发布局绘制流程。

89014c0e8a47cae4c6d207d64a87eb08.png

下图的systrace展示了UI数据从App到SurfaceFlinger的处理流程。从systrace上可以看到应用端有两个线程UI Thread和Render Thread用于处理应用想要更新的UI数据,其中UI Thread通过Choreographer配合Vsync信号有节奏的控制应用的绘制任务,并将所有要绘图的信息以绘图指令的形式记录到DisplayList里同步给Render Thread,Render Thread则将UI Thread传递过来的绘图数据送到GPU去做渲染。一旦同步工作完成,UI Thread就可以继续等下一个Vsync-app信号的到来,接着做下一帧的绘制。

Render Thread在做GPU渲染之前还需要申请一块buffer缓冲区用于存储GPU渲染的数据,这个buffer是应用通过Surface接口的dequeueBuffer方法向BufferQueue申请的,拿到buffer之后应用会调用OpenGL接口将绘制指令传递给GPU进行渲染,然后再通过queueBuffer函数将保存有渲染数据的buffer提交到SF作图层处理。

0c3c899099d922a3853a25bbfd8b6fad.png

值得注意的是在Android S以前,buffer状态都是由BufferQueue进行管理,而bufferQueue是在SF中创建的,应用端的dequeue、queue Buffer操作都是通过binder和SF进行交互。但是在Android S上,BufferQueue的创建从SF中移出来,变成BLASTBufferQueue去完成BufferQueue的创建,dequeue、queue、acquire、release Buffer 的操作均由 App 进行。当App绘制完一帧后,会通过BLASTBufferQueue接口执行onFrameAvailable回调,并通过transaction事务将该buffer提交到SF。

三、SF到HWC

当SF监听到Vsync-sf信号就会调用onMessageReceived函数来处理UI数据。

4c0de3e573ca5107287974ba248df1a8.png

onMessageReceived方法主要是用来处理两个Message:

INVALIDATE消息 -- onMessageInvalidate首先会调用handleMessageTransaction方法检查Layer/Display的属性和数量是否有变化;然后调用handleMessageInvalidate方法检查每个Layer是否有新提交的buffer, 如果有则通过handlePageFlip调用latchBuffer方法将BufferQueue中的buffer通过acquireBuffer拿走;最后还会检查HWC是否有repaint请求。上述三种情况只要有一种发生了,refreshNeeded就会被置为true,onMessageRefresh方法就会被调用做图像合成。

4ad67216a176ac0427deac9136efc056.png

REFRESH消息—onMessageRefresh方法则会对所有有buffer更新的Layer进行合成,大部分的合成工作是在present方法里完成的,这里SurfaceFlinger会和HWC进行交互,协同完成画面的合成。基本流程如下:

  1. SF为HWC提供完整的Layer列表并通过chooseCompositionStrategy方法询问合成策略。

  2. HWC根据硬件性能决定是使用硬件图层合成器还是GPU合成,并分别将每个Layer对应标记为overlay或GLES composition来进行响应。

  3. 需要硬件图层合成器合成的Layer直接由HWC处理,需要GPU合成的Layer则需要先由SF负责合成一个Layer后再和其他的Layer一起递交给HWC完成剩余的合成和显示。

当画面合成结束以后,SF还会调用postComposition做一些合成后的处理,其中就包括通过releaseBuffer释放SF在合成上一帧画面时拿到的所有buffer,以便应用在下次dequeueBuffer时能够拿到可用的buffer。

4e2fd52dcfbc2d3747fb09b23a59528d.png

下图的systrace展示了UI数据从SF到HWC的处理流程。当SF监听到Vsync-sf信号后会顺序执行INVALIDATE和REFRESH消息的回调函数,在执行onMessageRefresh方法时,SF和HWC会协同选择合成策略,并由HWC完成最终的画面合成。画面合成完成后,SF会通过transaction事务通知应用释放用于绘制上一帧画面的buffer。

59a4dce3dde60c35514f6816cfb9af36.png

四、HWC到屏幕

systrace上看到的都是软件上的一些操作,无法看到硬件的处理流程。而UI数据从HWC到屏幕的这个阶段只有一小段时间是在软件上进行的,大部分时间都是硬件在处理数据。我们首先来看看该阶段软件上的主要工作,HWC是通过DRM向屏幕输出画面的,DRM是linux内核的一个子系统,用于负责与显卡交互,因此HWC会先通过drmModeAtomicCommit接口向kernel提交Layer数据,drmModeAtomicCommit通过ioctl调用到kernel,然后通知disp thread也就是下图中所示的crtc_commit线程调用complete_commit函数完成剩下的合成工作。

a56a8331df449f014da13cc9363aa2e5.png

crtc_commit线程执行complete_commit方法时几乎一直处于D状态,表明此时DRM内的硬件正在做合成工作。经过一系列合成处理后最终的画面会通过DSI接口送到屏幕显示。至此,UI数据就完成了从应用端到硬件屏幕的旅程。

五、总结

一个buffer从被应用dequeue到最后HWC完成画面合成后由SF release的整个生命周期经历了如下流程:

  1. Vsync-app信号到达后,APP端由Choreographer顺序执行Input、Animation和Traversal的回调,然后通过dequeueBuffer拿到一个可用的buffer开始绘图,再通过queueBuffer将包含绘图数据的buffer提交到SF。

  2. Vsync-sf信号到达后,SF首先通过aquireBuffer获取所有Layer更新的buffer,然后根据Z-Order、透明度、大小、位置等参数对这些Layer进行图层处理,接着将所有的Layer送到HWC做合成。

  3. HWC对多个Layer做合成,合成完成后通过libdrm提供的接口通知DRM模块把图像显示到屏幕。

  4. 最终的画面送到屏幕后,HWC会将用完的buffer还给SF,SF会在下一个Vsync-sf信号到达后release被归还的buffer。

本文以UI数据在显示系统中的数据流向为指引,依次分析了App、SF、HWC和硬件屏幕处理UI数据的基本步骤。Android显示系统十分复杂,涉及模块较多,并且随着时间的推移也在不断更新优化,但是其处理UI数据的基本流向不会变,本文旨在帮助读者对显示系统有一个宏观的认识,其中的一些处理细节还需要读者通过阅读源码慢慢领会。

参考资料:

1.Android源码:https://cs.android.com/android/platform/superproject

2.Android图形系统篇总结:https://www.jianshu.com/p/180e1b6d0dcd

3.Android Systrace 基础知识:https://www.androidperformance.com/2019/05/28/Android-Systrace-About/

65f95cac3a2281d774f3565cb3327216.gif

长按关注内核工匠微信

Linux内核黑科技| 技术文章 | 精选教程

相关文章:

Android图形显示流程简介

注:本文缩写说明本文代码都是基于Android S一、概述本文将对从App画出一帧画面到这帧画面是如何到达屏幕并最终被人眼看到的这一过程进行简要分析,并将这其中涉及到的各个流程与其在systrace上的体现对应起来,期望最终能够让读者对Android系统…...

4.5.3 ArrayList

文章目录1.特点2. 练习:ArrayList测试3.ArrayList扩容1.特点 存在java.util包中内部是用数组结构存放数据,封装数组的操作,每个对象都有下标内部数组默认的初始容量是10,如果不够会以1.5倍的容量增长查询快,增删数据效率会低 2. 练习:ArrayList测试 package partThree;import…...

十二、Linux文件 - fseek函数讲解

目录 一、fseek函数讲解 二、fseek函数实战 一、fseek函数讲解 重定向文件内部的指针 注:光标 ---- 文件内部的指针 函数原型: int fseek(FILE *stream,long offset,int framewhere) 参数: stream:文件指针offset:…...

Python3.10新特性之match语句示例详解

这篇文章主要为大家介绍了Python3.10新特性之match语句示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪正文在Python 3.10发布之前,Python是没有类似于其他语言中switch语句的&…...

虎牙盈利能力得到改善,但监管风险对其收入产生负面影响

来源:猛兽财经 作者:猛兽财经 监管风险再次成为焦点 过去一段时间,与中概股相关的监管风险再次引起了投资者的注意,这也是正在考虑投资虎牙(HUYA)的投资者需要注意的问题。 例如,监管机构在2022…...

HBase 分布式搭建

前言: 请先确保 Hadoop 集群搭建完成。 Hadoop 完全分布式搭建(超详细)搭建环境介绍: 三台主机,一主两从,系统为 Centos 7.5。 相关组件版本信息如下: jdk1.8hadoop-3.1.3zookeeper-3.5.7hbase-2.2.3注意,以下安装教程中涉及到的路径请替换成自己的! ZooKeeper 安…...

【Python】修改枚举的取值及链式调用

author: jwensh date: 2023.02.11 文章目录枚举的取值及链式调用需求背景1. enum.key 即获取值(而不是 enum.key.value)2. 多级链式调用枚举的取值及链式调用 需求背景 测试过程中需要很多参数化的设置及编程规范要求,希望修改数据不修改代…...

复现篇--zi2zi

intro: 用GAN学习东亚语言字体。zi2zi(意思是从字符到字符)是最近流行的pix2pix模型在汉字上的应用和扩展。 article:https://kaonashi-tyc.github.io/2017/04/06/zi2zi.html code:https://github.com/kaonashi-tyc/zi2zi pytorch版本:https://github.com/EuphoriaYan/zi2…...

153、【动态规划】leetcode ——416. 分割等和子集:滚动数组(C++版本)

题目描述 原题链接:1049. 最后一块石头的重量 II 解题思路 本题要找的是最小重量,我们可以将石头划分成两个集合,当两个集合的重量越接近时,相减后,可达到的装量就会是最小,此时本题的思路其实就类似于 4…...

linux head命令(head指令)(获取文件或管道输出结果前n行,默认前10行)与sed命令区别

head命令是一个在Linux系统中常用的命令,用于读取文件的前几行(默认读取前10行) 文章目录使用方法读取文件的前10行:head filename读取文件的前n行:head -n行数 filename读取多个文件的前几行:head -n 行数…...

Mysql数据库09——分组聚合函数

类似pandas里面的groupby函数,SQL里面的GROUP BY子句也是可以达到分组聚合的效果。 常用的聚合函数有COUNT(),SUM(),AVG(),MAX(),MIN(),其用法看名字都看的出来,下面一一介绍 聚合函数 COUNT()计数 统计student表中计科系学生的人数。 SE…...

第43章 菜单实体及其约束规则的定义实现

1 Core.Domain.Security.Menu namespace Core.Domain.Security { /// <summary> /// 【菜单--类】 /// <remarks> /// 摘要&#xff1a; /// 通过该实体类及其属性成员&#xff0c;用于实现当前程序【Core】.【领域】.【安全】.【菜单】实体与“[ShopDemo].[…...

OpenAI最重要的模型【CLIP】

最近的 AI 突破 DALLE和 Stable Diffusion有什么共同点&#xff1f; 它们都使用 CLIP 架构的组件。 因此&#xff0c;如果你想掌握这些模型是如何工作的&#xff0c;了解 CLIP 是先决条件。 此外&#xff0c;CLIP 已被用于在 Unsplash 上索引照片。 但是 CLIP 做了什么&…...

分享112个JS菜单导航,总有一款适合您

分享112个JS菜单导航&#xff0c;总有一款适合您 112个JS菜单导航下载链接&#xff1a;https://pan.baidu.com/s/1Dm73d2snbu15hZErJjTXxg?pwdfz1c 提取码&#xff1a;fz1c Python采集代码下载链接&#xff1a;https://wwgn.lanzoul.com/iKGwb0kye3wj base_url "h…...

MySQL 3:MySQL数据库基本操作 DQL

数据库管理系统的一个重要功能是数据查询。数据查询不应简单地返回数据库中存储的数据&#xff0c;还应根据需要对数据进行过滤&#xff0c;确定数据的显示格式。MySQL 提供了强大而灵活的语句来实现这些操作。MySQL数据库使用select语句查询数据。 select [all|distinct]<…...

sql语句的优化

sql优化 优化数据访问 查询性能低下最基本的原因是访问的数据太多&#xff0c;大部分性能低下的查询都可以通过减少访问的数据量来优化所以关于低效的查询&#xff0c;需要确认是否检索了大量不需要的数据&#xff0c;以及mysql服务器层是否在分析大量不需要的数据 因为有些查…...

Shell脚本之——自动安装JDK

目录 1.修改主机名 2.创建文件&#xff0c;单独存放Shell脚本 3.编写Shell脚本 4.Shell脚本命令简介 (1)文件头 (2)打印命令 (3)设置全局变量 (4)条件判断 (5)解压 (6)文件重命名 (7)在/etc/profile指定行插入 5.完整脚本内容 6.重启环境变量 7.判断java是否配置…...

大数据---Hadoop安装Hadoop简易版

编写自动安装Hadoop的shell脚本 完整流程: 大数据—Hadoop安装教程&#xff08;二&#xff09; 文章目录编写自动安装Hadoop的shell脚本上传压缩包编写shell脚本vim hadoopautoinstall.sh运行上传压缩包 在opt目录下创建连个目录install和soft 将压缩包上传到install目录下 …...

Spring框架中使用到的设计模式以及对应的类(方法)

模板方法--->postProcessBeanFactory&#xff0c;onFresh、initPropertySource装饰器模式--->BeanWrapper委托者模式--->BeanDefinitionParseDelegate策略模式--->ClassPathXmlApplicationContext、FileSystemApplicationContext、XMLBeanDefinitionReader、Proper…...

类和类的定义

6.2 类和类的定义 面向对象最重要的概念就是类&#xff08;Class&#xff09;和实例&#xff08;Instance&#xff09;&#xff0c;必须牢记类是抽象的模板&#xff0c;比如学生类&#xff0c;而实例是根据类创建出来的一个个具体的对象&#xff0c;每个对象都拥有相同的方法&…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...