【Android GUI】从总体上了解Android的GUI体系

文章目录

  • 概览
    • Android硬件接口HAL
    • Gralloc与Framebuffer
  • Gralloc模块的加载
  • Gralloc提供的接口
  • Android原生的Gralloc实现
    • 打开framebuffer设备
    • 打开gralloc设备
  • 参考

概览

在这里插入图片描述

  • Linux内核提供了统一的framebuffer显示驱动。设备节点/dev/graphics/fb*或者/dev/fb*,其中fb0表示第一个Monitor。

  • Android的HAL层提供了Gralloc,包括fb和gralloc两个设备。fb负责打开内核的framebuffer、初始化配置。gralloc管理帧缓冲区的分配和释放。所以上层只需要通过Gralloc来间接访问帧缓冲区,来保证对framebuffer的统一管理。

  • HAL层的composer为UI合成提供接口,被surface flinger调用。

  • VSync是“Project Butter”加入的同步机制,可以通过硬件产生,也可以通过软件,即VSyncThread模拟。

  • OpenGL ES 是一个通用函数库,需要和具体平台建立关联才可以工作。

  • FramebufferNativeWindow负责OpenGL ES在Android平台本地化的中介之一

  • EGL为OpenGL ES配置本地窗口。

Android硬件接口HAL

HAL是Android很多子系统,例如显示系统、音频系统等和Linux kernel驱动之间通信的统一接口。

Gralloc与Framebuffer

Framebuffer是内核系统提供的图形硬件的抽象描述,它占用了系统存储空间的一部分,是一块包含屏幕显示信息的缓冲区。
Android中,Framebuffer提供的设备文件节点是/dev/graphics/fb*

Android的显示系统借助于HAL层的Gralloc操作帧缓冲区。

Gralloc模块的加载

Gralloc对应的模块是由FramebufferNativeWindow在构造函数中加载的。

hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
#define GRALLOC_HARDWARE_MODULE_ID "gralloc"

hw_get_module查找和ID值匹配的库:

#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"

lib库的命名形式:

gralloc.[ro.hardware].so
gralloc.[ro.product.board].so
gralloc.[ro.board.platform].so
gralloc.[ro.arch].so

默认的:

    gralloc.default.so

Gralloc提供的接口

/*hardware/libhardware/include/hardware/Hardware.h*/
typedef struct hw_module_t {struct hw_module_methods_t* methods;//一个HAL库必须提供的方法} hw_module_t;typedef struct hw_module_methods_t {int (*open)(const struct hw_module_t* module, const char* id,struct hw_device_t** device);
} hw_module_methods_t;

前面提供的架构图中,open接口可以帮助上层打开“fb0”和“gpu0”。fb0就是主屏幕,gpu0负责图形缓冲区的分配和释放。

/*frameworks/native/libs/ui/FramebufferNativeWindow.cpp*/
FramebufferNativeWindow::FramebufferNativeWindow()
: BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
{…err = framebuffer_open(module, &fbDev); //打开fb设备err = gralloc_open(module, &grDev);//打开gralloc设备

Android原生的Gralloc实现

Android原生态的Gralloc实现在hardware/libhardware/modules/gralloc中,它open接口对应的是:

/*hardware/libhardware/modules/gralloc/Gralloc.cpp*/
int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device)
{int status = -EINVAL;if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {//打开gralloc设备} else {status = fb_device_open(module, name, device);//否则就是fb设备}return status;
}

打开framebuffer设备

/*hardware/libhardware/modules/gralloc/Framebuffer.cpp*/
int fb_device_open(hw_module_t const* module, const char* name, hw_device_t** device)
{int status = -EINVAL;if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {//设备名是否正确fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));/分配hw_device_t空间,   这是一个“壳”*/memset(dev, 0, sizeof(*dev));//初始化,良好的编程习惯…dev->device.common.close = fb_close;//这几个接口是fb设备的核心dev->device.setSwapInterval = fb_setSwapInterval;dev->device.post = fb_post;…private_module_t* m = (private_module_t*)module;status = mapFrameBuffer(m);//内存映射,以及参数配置if (status >= 0) {*device = &dev->device.common;//“壳”和“核心”的关系}}return status;
}

标准的fb设备需要实现:int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);,将buffer数据post到屏幕上 ,这样buffer内容在下一次VSYNC中被显示出来。
设置缓冲区swap的时间间隔:int (*setSwapInterval)(struct framebuffer_device_t* window, int interval);
设置刷新区域:int (*setUpdateRect)(struct framebuffer_device_t* window, int left, int top, int width, int height);

接着是打开kernel层的fb设备和对fb进行配置,在mapFrameBuffer()中完成,它会尝试打开:

"/dev/graphics/fb%u"或者 "/dev/fb%u"

打开后,通过

ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
ioctl(fd, FBIOGET_VSCREENINFO, &info)

得到屏幕参数,接着通过ioctl(fd, FBIOPUT_VSCREENINFO, &info)对fb进行配置。

mapFrameBuffer()的另外一个任务是做为fb设备做内存映射:

    void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);    module->framebuffer->base = intptr_t(vaddr);memset(vaddr, 0, fbSize);

打开gralloc设备

/*hardware/libhardware/modules/gralloc/Gralloc.cpp*/
int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device)
{int status = -EINVAL;if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {gralloc_context_t *dev;//做法和fb类似dev = (gralloc_context_t*)malloc(sizeof(*dev));//分配空间/* initialize our state here */memset(dev, 0, sizeof(*dev));…dev->device.alloc = gralloc_alloc; //从提供的接口来看,gralloc主要负责“分配和释放”操作dev->device.free = gralloc_free;}

总结下Android原生的Gralloc:
在这里插入图片描述

参考

《深入理解Android内核设计思想》

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

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

相关文章

快速上手Linux核心命令

Linux 的重要性不用我多说了吧,大多数互联网公司,服务器都是采用的Linux操作系统 Linux是一个主要通过命令行来进行管理的操作系统。 只有熟练掌握Linux核心命令,在使用起来我们才会得心应手 这里给大家整理了Linux一些核心命令&#xff0…

Android --- Activity

官方文档-activity Activity 提供窗口,供应在其中多个界面。此窗口通常会填满屏幕,但也可能小于屏幕并浮动在其他窗口之上。 大多数应用包含多个屏幕,这意味着它们包含多个 Activity。通常,应用中的一个 Activity 会被指定主 Ac…

分布式限流——Redis + Lua实现滑动窗口算法

Zset(有序集合)在Redis中用来实现滑动窗口限流的主要思路是利用其自动排序和可过期成员的特点: 初始化及数据结构选择: 为需要限流的接口或服务创建一个唯一的键(key)对应一个Zset。Zset中的每个成员通常是…

SQL常用脚本查询大全,包含优化

创建25个具体的优化语句及其说明确实是一个庞大的任务,特别是考虑到不同的数据库和查询场景需要不同的优化策略。 我将继续提供一系列的优化示例和技巧,这将帮助涵盖更多常见的优化场景。 1. 避免使用HAVING来过滤行 -- 使用WHERE过滤条件&…

JAVA基础08- 继承,重写,super以及this

目录 继承(extends) 定义 说明 作用 方法的重写 定义 重写关键点 方法重写与重载的区别 练习 练习1(方法继承与重写的简单练习) 练习2(方法继承与重写的进阶练习) This的使用 定义 作用以及注…

DevOps(六)Git特点和命令详解

Git 是一个分布式版本控制系统,用于跟踪软件开发过程中对文件的修改,使得团队成员可以在不同的地方工作,同时保持代码的一致性和完整性。它由 Linus Torvalds 于 2005 年开发,主要用于 Linux 内核的开发,后来被广泛应用…

基于SpringBoot+Vue的IT技术交流平台(源码+文档+包运行)

一.系统概述 我国科学技术的不断发展,计算机的应用日渐成熟,其强大的功能给人们留下深刻的印象,它已经应用到了人类社会的各个层次的领域,发挥着重要的不可替换的作用。信息管理作为计算机应用的一部分,使用计算机进行…

leetcode-分割链表

题目 面试题 02.04. 分割链表 提示 给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你不需要 保留 每个分区中各节点的初始相对位置。 示例 1: 输入&#xff…

搜维尔科技:【工业仿真】煤矿安全知识基础学习VR系统

产品概述 煤矿安全知识基础学习VR系统 系统内容: 煤矿安全知识基础学习VR系统内容包括:下井流程(正确乘坐罐笼、班前会、井下行走注意事项、工作服穿戴、入井检身及人员清点、下井前准备工作、提升运输安全);运煤流程…

SpringBoot集成RockerMQ

1.引入依赖 <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.2.0</version> </dependency>2.配置服务器地址 #Rocketmq配置 rocketmq.name-server192…

专业清洁工匠服务网站模板 html网站

目录 一.前言 二.页面展示 三.下载链接 一.前言 该HTML代码生成了一个网页&#xff0c;包括以下内容&#xff1a; 头部信息&#xff1a;指定了网页的基本设置和元数据&#xff0c;例如字符编码、视口大小等。CSS文件&#xff1a;引入了多个CSS文件&#xff0c;用于设置网页…

EI级 | Matlab实现VMD-TCN-LSTM-MATT变分模态分解卷积长短期记忆神经网多头注意力多变量时间序列预测

EI级 | Matlab实现VMD-TCN-LSTM-MATT变分模态分解卷积长短期记忆神经网多头注意力多变量时间序列预测 目录 EI级 | Matlab实现VMD-TCN-LSTM-MATT变分模态分解卷积长短期记忆神经网多头注意力多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实…

MySQL 开源到商业(一):Sun 公司收购了 MySQL AB

2008 年 1 月 27 日&#xff0c;开源数据库 MySQL 之父 Monty 在博客上高调宣布 Sun 公司收购了 MySQL AB。在这篇博客里面 Monty 分享了对于开源项目出路的思考&#xff0c;以及作为一个开源骇客对大公司收购的看法。目前国内开源项目正在爆发&#xff0c;而对开源的思考也在逐…

动手写sql 《牛客网80道sql》

第1章&#xff1a;SQL编写基础逻辑和常见问题 基础逻辑 SELECT语句: 选择数据表中的列。FROM语句: 指定查询将要从哪个表中检索数据。WHERE语句: 过滤条件&#xff0c;用于提取满足特定条件的记录。GROUP BY语句: 对结果进行分组。HAVING语句: 对分组后的结果进行条件过滤。O…

【STM32】嵌入式实验二 GPIO 实验 (前三个设计)

1&#xff0e; 按键亮灯 设计 GPIO 实验项目 1&#xff0c;功能&#xff1a;当按键 KB1 按下时&#xff0c;实验板上全彩发光二极管周边 的发光二极管全亮&#xff0c;当按键 KB2 按下时跑马灯 D0 闪亮。 实验要求基于寄存器的GPIO配置&#xff0c;所以需要手动操作寄存器来配…

2024年4月13日美团春招实习试题【第一题:好子矩阵】-题目+题解+在线评测【模拟】

2024年4月13日美团春招实习试题【第一题:好子矩阵】-题目题解在线评测【模拟】 题目描述&#xff1a;输入描述输出描述样例 解题思路一&#xff1a;模拟解题思路二&#xff1a;思路二解题思路三&#xff1a;直接判断 题目描述&#xff1a; 塔子哥定义一个矩阵是”好矩阵”&…

联想小新Air14-2019锐龙版更换硬盘

首先打下D面所有螺丝&#xff08;内六角螺丝&#xff0c;需要准备螺丝刀&#xff09;&#xff0c;然后从下方翘起整个D面打开如下图 原装为2280长度的海力士硬盘&#xff0c;有空余的2242长度硬盘位 更换前断电&#xff0c;建议拆下电池&#xff08;扣下电池排线后不好安装&am…

密码学 | 多重签名:基本概念

目录 摘要 1 什么是多重签名&#xff1f; 2 多重签名的作用 2.1 联名账户 2.2 提高安全性 2.3 秘钥备份 3 比特币的多重签名 3.1 对比一 3.2 对比二 3.2.1 线性性 3.2.2 不可延展性 3.2.3 安全性证明 3.2.4 效率高、占用空间少 ⚠️原文&#xff1a;多…

每日OJ题_完全背包④_力扣279. 完全平方数(一维和二维)

目录 力扣279. 完全平方数 问题解析 解析代码 优化代码&#xff08;相同子问题分析和滚动数组&#xff09; 力扣279. 完全平方数 279. 完全平方数 难度 中等 给你一个整数 n &#xff0c;返回 和为 n 的完全平方数的最少数量 。 完全平方数 是一个整数&#xff0c;其值…

百科不全书之 docker记录

docker记录 1 参考文件2. Docker简介与虚拟机的区别 1 参考文件 参考视频&#xff1a;B站【GeekHour】30分钟Docker入门教程: link 2. Docker简介 Docker是一个用于构建运行 传送 应用程序的平台。 与虚拟机的区别 虚拟机使用了一种叫做虚拟化的技术。每台虚拟机需要占…