Android显示系统(10)- SurfaceFlinger内部结构

news2025/1/16 2:45:47

一、前言:

之前讲述了native层如何使用SurfaceFlinger,我们只是看到了简单的API调用,从本文开始,我们逐步进行SurfaceFlinger内部结构的分析。话不多说,莱茨狗~

二、类图:

2.1、总体架构:

先看下SurfaceFlinger的关键成员和我们BootAnimation侧关键成员如何对应起来,这不是严格的UML类图,但是这么画我觉着很容易理解,就先这么画了。
在这里插入图片描述

可以看出:

  • SurfaceFlinger侧会为BootAnimation创建一个Client,其实,SF会为每个APP都创建一个Client;
  • SurfaceFlinger侧有一个BufferQueueLayer(Layer的子类)对应APP侧的SurfaceControl,允许有一个APP有多个Layer,同时,SF会生成多个SurfaceControl
  • BufferQueueLayer是一个buffer队列,队列有一个消费者mConsumer和一个生产者mProducer
  • APP侧的SurfaceControl当中有一个Surface
  • Surface当中又有一个数组mSlots表示64个buffer,对应SF当中其实也有这么一个数组,如果数组来管理这些buffer,这个是比较复杂的流程,后面单独写一篇文章介绍;

2.2、代理关系:

上面看到好多类似于SurfaceCompser的字眼,到底啥关系呢?我给你画个图:

在这里插入图片描述

熟悉Binder机制的朋友都应该能看懂,Bpxxxx一般就是代理类,Bnxxxx一般就是本地类,这样APP侧调用mClient就像调用Client一模一样的,底层Binder帮你处理了。一种RPC的思想。

三、APP连接SurfaceFlinger:

前面画了静态的类图,接下来我们看下APP如何去和SurfaceFlinger建立连接。

  1. APP侧获得SurfaceFlinger服务:

    • BootAnimation构造函数中,我们会通过mSession = new SurfaceComposerClient();来获取SF的代理类。

      BootAnimation::BootAnimation(sp<Callbacks> callbacks)
              : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
              mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) {
          // SurfaceFlinger在客户端的代理
          mSession = new SurfaceComposerClient();
          // 。。。删除非关键代码
      }
      
  2. 强引用SF服务:

    • 强引用时候就会执行SurfaceComposerClient::onFirstRef()

      void BootAnimation::onFirstRef() {
          // 将当前 BootAnimation 对象链接到图形服务的死亡通知。这意味着如果图形服务崩溃或退出,当前对象将收到通知。
          status_t err = mSession->linkToComposerDeath(this);
          if (err == NO_ERROR) {
              // 预加载开机动画文件
              preloadAnimation();
      		// 。。。
          }
      }
      
    • 里面会调用conn = sf->createConnection();这里面的sf表示SurfaceFlinger,调用这个方法就可以在SF当中创建一个Client了。

      void SurfaceComposerClient::onFirstRef() {
          sp<ISurfaceComposer> sf(ComposerService::getComposerService());
          if (sf != nullptr && mStatus == NO_INIT) {
              sp<ISurfaceComposerClient> conn;
              // 调用这句之后,SF侧会创建一个Client来对应APP
              conn = sf->createConnection();
              if (conn != nullptr) {
                  mClient = conn;
                  mStatus = NO_ERROR;
              }
          }
      }
      
    • BpSurfaceComposer当中发起Binder调用:

          virtual sp<ISurfaceComposerClient> createConnection()
          {
              Parcel data, reply;
              data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
              // 发起Binder调用
              remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
              return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
          }
      
    • SurfaceFlinger侧创建Client:

      SurfaceFlinger端通过onTransact收到CREATE_CONNECTION消息并处理:

      status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                          uint32_t flags) {
          status_t credentialCheck = CheckTransactCodeCredentials(code);
          if (credentialCheck != OK) {
              return credentialCheck;
          }
          // 调用了父类BnSurfaceComposer的方法去处理消息
          status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
          // ...
      }
      

      看到没有,转手就调用了父类的onTransact方法:

      status_t BnSurfaceComposer::onTransact(
          uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
      {
          switch(code) {
              case CREATE_CONNECTION: { // 处理链接,创建Client
                  CHECK_INTERFACE(ISurfaceComposer, data, reply);
                  sp<IBinder> b = IInterface::asBinder(createConnection());
                  reply->writeStrongBinder(b);
                  return NO_ERROR;
              }
              // 。。。
      	}
      	// 。。。
      }
      

      由于C++的多态性,父类指针指向子类对象,因此这个createConnection方法属于子类SurfaceFlinger的:

      sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
          return initClient(new Client(this));
      }
      

      至此,Client就创建好了。

四、总结:

本文主要讲了SurfaceFlinger内部几个非常重要的概念,并且,分析了APP和SurfaceFlinger建立连接的时候,SurfaceFlinger干了啥,后续再分析:如何获取画布,如何往画布上作图,如何提交已经做好图的画布,并且会专门分析buffer管理。

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

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

相关文章

PPT技巧:将幻灯片里的图片背景设置为透明

在PPT中添加了图片&#xff0c;想要将图片中的背景设置为透明或者想要抠图&#xff0c;有什么方法吗&#xff1f;今天分享两个方法。 方法一&#xff1a; 添加图片&#xff0c;选中图片之后&#xff0c;点击【图片格式】功能&#xff0c;点击最左边的【删除背景】 PPT会自动帮…

以太网链路详情

文章目录 1、交换机1、常见的概念1、冲突域2、广播域3、以太网卡1、以太网卡帧 4、mac地址1、mac地址表示2、mac地址分类3、mac地址转换为二进制 2、交换机的工作原理1、mac地址表2、交换机三种数据帧处理行为3、为什么会泛洪4、转发5、丢弃 3、mac表怎么获得4、同网段数据通信…

CNCF云原生生态版图

CNCF云原生生态版图 概述什么是云原生生态版图如何使用生态版图 项目和产品&#xff08;Projects and products&#xff09;会员&#xff08;Members&#xff09;认证合作伙伴与提供商&#xff08;Certified partners and providers&#xff09;无服务&#xff08;Serverless&a…

每日计划-1212

1. 完成 SQL1 查询所有列 2. 八股部分 1) C 中多态性在实际项目中的应用场景有哪些&#xff1f; &#xff08;1&#xff09;图形绘制系统 场景描述&#xff1a;在一个图形绘制软件中&#xff0c;可能有多种图形&#xff0c;如圆形、矩形、三角形等。每种图形都需要有自己的…

Autosar CP RTE:一个例子简要介绍工作原理

以下是一个示例&#xff0c;展示如何通过AUTOSAR的RTE机制利用配置&#xff08;ARXML文件&#xff09;来实现软件组件集成&#xff0c;包含对应的C源代码以及模拟自动生成的RTE框架代码的示例。请注意&#xff0c;实际的AUTOSAR项目会复杂得多&#xff0c;这里只是一个简化且示…

动手学深度学习---预备知识

深度学习是关于优化的学习。对一个带有参数的模型&#xff0c;找到其中能拟合数据最好的模型。 一、数据操作 张量&#xff1a;表示一个由数值组成的数组&#xff0c;这个数组可能有多个维度。具有一个轴的张量对应数学上的向量&#xff0c;具有两个轴的张量对应数学上的矩阵&…

频域采样引起Gibbs效应——频域采样FIR滤波器设计的主要问题(答作者问)

还是这个图&#xff0c;我不明白廖老师为什么纠结这几个图不放过。Rafael Gonzalez的《数字图像处理》概念不清楚的地方&#xff0c;我就直接放过了&#xff0c;我为什么要和基础差的人纠结。 现在的问题是图(c )到图(d)为什么会产生Gibbs效应。这与补零&#xff08;哪怕是异想…

《Keras3 minist 手写数字AI模型训练22秒精度达到:0.97》

《Keras3 minist 手写数字AI模型训练22秒精度达到&#xff1a;0.97》 一、修改源码加上如下两条代码二、源码修改如下三、Keras3 minist 训练22秒结束&#xff0c;训练过程截图四、Keras3 minist 源码截图 一、修改源码加上如下两条代码 import os os.environ["KERAS_BAC…

R语言——缺失值处理

目录 缺失数据 1 R中的缺失值 2查看缺失值is.na() 3 去除缺失值 1 R中的缺失值 在R中&#xff0c;NA代表缺失值&#xff0c;NA是不可用&#xff08;可能是0&#xff0c;可能是其他值&#xff0c;NA是未知的&#xff09;&#xff0c;notavailable的简称&#xff0c;用来存储…

找不到共享打印机0x00000bc4报错多种解决方法

在访问共享打印机提示"找不到打印机0x00000bc4"解决方法怎么解决&#xff1f;今天小编就教大家找不到共享打印机0x00000bc4报错多种解决方法 找不到共享打印机0x00000bc4报错多种解决方法原因分析&#xff1a; 1、检查打印机驱动&#xff1a;一般出现这种情况是由于打…

vulhub复现CVE-2021-44228log4j漏洞

目录 一&#xff1a;漏洞概述 二&#xff1a;漏洞原理 三&#xff1a;漏洞利用 lookup功能&#xff1a; JNDI解析器&#xff1a; ldap服务&#xff1a; RMI&#xff1a; 四&#xff1a;漏洞复现 4.1靶场 4.2dnslog测试 4.3部署jndi-injection-exploit 4.4打开监听端口 4.5触发请…

论文笔记:Treat Visual Tokens as Text? But Your MLLM Only Needs Fewer Efforts to See

2024 10月的arxiv 1 主要idea 针对多模态大模型&#xff08;如LLaVA&#xff09;&#xff0c;提出了一系列高效的剪枝策略 在显著降低计算开销&#xff08;多达 88%&#xff09;的同时&#xff0c;保持了模型在多模态任务中的性能表现 2 目前的问题 与文本 token 相比&…

MySQL常用运维操作(一):快速复制一张表

假设有如下表结构&#xff1a; -- 创建表db1.t create database db1; use db1; create table t(id int primary key,a int, b int, index(a))engineinnodb;-- 向表t写入1000行数据 delimiter ;;create procedure idata()begindeclare i int;set i1;while(i<1000)doinsert i…

怎么确定目标主机,整个网络过程

怎么确定目标主机&#xff0c;整个网络过程 简单来说&#xff0c; 就是归结于计算机间怎么进行通信&#xff0c; &#xff08;原始方法&#xff09; 简单点直接加网线&#xff0c;但 一个设备的网口肯定是有限的 当相连的设备多了&#xff0c;整个网线将变得十分复杂&#…

机器视觉与OpenCV--01篇

计算机眼中的图像 像素 像素是图像的基本单位&#xff0c;每个像素存储着图像的颜色、亮度或者其他特征&#xff0c;一张图片就是由若干个像素组成的。 RGB 在计算机中&#xff0c;RGB三种颜色被称为RGB三通道&#xff0c;且每个通道的取值都是0到255之间。 计算机中图像的…

【H3CNE邓方鸣】配置链路聚合+2024.12.11

文章目录 链路聚合作用负载分担分类静态聚合动态聚合 链路聚合作用 定义&#xff1a;把连接到统一交换机上的多个物理端口捆绑为一个逻辑端口 增加链路带宽&#xff1a;聚合组内只要还有物理端口存活&#xff0c;链路就不会中断 提供链路可靠性&#xff1a;避免了STP计算&…

Java 基础知识——part 1

1.目前Java平台有三种版本&#xff1a; Java SE&#xff1a;用于开发桌面应用程序 Java EE&#xff1a;用于编写企业级应用程序 Java ME&#xff1a;用于开发设备应用程序 2.Applet可嵌入Web文档的一种小型程序&#xff0c;因网络传输速度关系都很短小 3.Appilication&…

数据可视化的Python实现

一、GDELT介绍 GDELT ( www.gdeltproject.org ) 每时每刻监控着每个国家的几乎每个角落的 100 多种语言的新闻媒体 -- 印刷的、广播的和web 形式的&#xff0c;识别人员、位置、组织、数量、主题、数据源、情绪、报价、图片和每秒都在推动全球社会的事件&#xff0c;GDELT 为全…

nginx反向代理(负载均衡)和tomcat介绍

nginx的代理 负载均衡 负载均衡的算法 负载均衡的架构 基于ip的七层代理 upstream模块要写在http模块中 七层代理的调用要写在location模块中 轮询 加权轮询 最小连接数 ip_Hash URL_HASH 基于域名的七层代理 配置主机 给其余客户机配置域名 给所有机器做域名映射 四层代理…

Qt编写RK3588视频播放器/支持RKMPP硬解/支持各种视音频文件和视频流/海康大华视频监控

一、前言 用ffmpeg做硬解码开发&#xff0c;参考自带的示例hw_decode.c即可&#xff0c;里面提供了通用的dxva2/d3d11va/vaapi这种系统层面封装的硬解码&#xff0c;也就是无需区分用的何种显卡&#xff0c;操作系统自动调度&#xff0c;基本上满足了各种场景的需要&#xff0…