安卓recovery流程分析(编译、界面、图片)
目录
recovery 界面菜单
recovery 界面操作
recovery 启动流程
recovery 编译makefile
recovery 图片大小
ramdisk、boot.img、recovery.img之间的关系
author | daisy.skye的博客_CSDN博客-嵌入式,Qt,Linux领域博主 |
recovery 界面菜单
recovery 界面显示 | android recoveryuse |
路径 | bootable/recovery/device.cpp |
背景设置 | void ScreenRecoveryUI::draw_background_locked() { gr_color(0, 0, 0, 255); } 第一个参数 0:表示红色分量的强度,这里是最小值,表示没有红色。 第二个参数 0:表示绿色分量的强度,这里是最小值,表示没有绿色。 第三个参数 0:表示蓝色分量的强度,这里是最小值,表示没有蓝色。 第四个参数 255:表示透明度或不透明度,这里是最大值,表示完全不透明。 因此,gr_color(0, 0, 0, 255) 表示的是一个完全不透明的黑色。 如果要设置绿色不透明背景,修改参数为gr_color(0, 255, 0, 255) |
路径 | bootable/recovery/screen_ui.cpp |
#include "device.h"
static const char* MENU_ITEMS[] = {"Reboot system now","Reboot to bootloader","Apply update from ADB","Apply update from SD card","Wipe data/factory reset",
#ifndef AB_OTA_UPDATER"Wipe cache partition",
#endif // !AB_OTA_UPDATER"Mount /system","View recovery logs","Run graphics test","Power off",NULL,
};static const Device::BuiltinAction MENU_ACTIONS[] = {
Device::REBOOT,
Device::REBOOT_BOOTLOADER,
Device::APPLY_ADB_SIDELOAD,
Device::APPLY_SDCARD,
Device::WIPE_DATA,
#ifndef AB_OTA_UPDATER
Device::WIPE_CACHE,
#endif // !AB_OTA_UPDATER
Device::MOUNT_SYSTEM,
Device::VIEW_RECOVERY_LOGS,
Device::RUN_GRAPHICS_TEST,
Device::SHUTDOWN,
};static_assert(sizeof(MENU_ITEMS) / sizeof(MENU_ITEMS[0]) ==sizeof(MENU_ACTIONS) / sizeof(MENU_ACTIONS[0]) + 1,"MENU_ITEMS and MENU_ACTIONS should have the same length, ""except for the extra NULL entry in MENU_ITEMS.");const char* const* Device::GetMenuItems() {return MENU_ITEMS;
}
这段代码定义了两个数组:MENU_ITEMS和MENU_ACTIONS。这两个数组用于存储菜单项和对应的操作。
MENU_ITEMS是一个字符串数组,包含了一系列菜单项的名称。每个菜单项都是一个字符串常量。
MENU_ACTIONS是一个Device::BuiltinAction类型的数组,用于存储与每个菜单项对应的操作。Device::BuiltinAction是一个枚举类型,表示设备的内置操作,如重启、应用更新、擦除数据等。
在MENU_ITEMS数组的末尾,有一个NULL指针,表示数组的结束。
代码中的GetMenuItems()函数返回了MENU_ITEMS数组的地址,即菜单项的名称数组的地址。
最后,代码使用了static_assert语句来确保MENU_ITEMS和MENU_ACTIONS数组的长度相同,除了MENU_ITEMS数组中的额外的NULL条目。如果长度不同,编译时将会报错。
recovery 界面操作
代码中的GetMenuItems()函数返回了MENU_ITEMS数组的地址,即菜单项的名称数组的地址。具体经过switch和case进行具体的操作
// Return REBOOT, SHUTDOWN, or REBOOT_BOOTLOADER. Returning NO_ACTION
// means to take the default, which is to reboot or shutdown depending
// on if the --shutdown_after flag was passed to recovery.
static Device::BuiltinAction
prompt_and_wait(Device* device, int status) {for (;;) {finish_recovery(NULL);switch (status) {case INSTALL_SUCCESS:case INSTALL_NONE:
ui->SetBackground(RecoveryUI::NO_COMMAND);break;case INSTALL_ERROR:case INSTALL_CORRUPT:
ui->SetBackground(RecoveryUI::ERROR);break;}
ui->SetProgressType(RecoveryUI::EMPTY);int chosen_item = get_menu_selection(nullptr, device->GetMenuItems(), 0, 0, device);// device-specific code may take some action here. It may// return one of the core actions handled in the switch// statement below.
Device::BuiltinAction chosen_action = device->InvokeMenuItem(chosen_item);bool should_wipe_cache = false;switch (chosen_action) {case Device::NO_ACTION:break;case Device::REBOOT:case Device::SHUTDOWN:case Device::REBOOT_BOOTLOADER:return chosen_action;case Device::WIPE_DATA:wipe_data(ui->IsTextVisible(), device);if (!ui->IsTextVisible()) return Device::NO_ACTION;break;case Device::WIPE_CACHE:wipe_cache(ui->IsTextVisible(), device);if (!ui->IsTextVisible()) return Device::NO_ACTION;break;case Device::APPLY_ADB_SIDELOAD:case Device::APPLY_SDCARD://省略代码…… break;case Device::VIEW_RECOVERY_LOGS:choose_recovery_file(device);break;case Device::RUN_GRAPHICS_TEST:run_graphics_test(device);break;case Device::MOUNT_SYSTEM:
#ifdef USE_MDTPif (is_mdtp_activated()) {
ui->Print("Mounting /system forbidden by MDTP.\n");}else
#endif//省略代码…… break;}}
}
这段代码定义了一个函数prompt_and_wait,该函数用于提示用户选择一个操作,并等待用户的输入。
函数的参数包括一个指向Device对象的指针device和一个整数status。
函数使用一个无限循环for (;;) {}来不断执行以下操作:
调用finish_recovery(NULL)函数,完成recovery操作的最后步骤。
根据status的值,设置recovery界面的背景和进度条的类型。
如果status的值是INSTALL_SUCCESS或INSTALL_NONE,则将背景设置为RecoveryUI::NO_COMMAND;如果status的值是INSTALL_ERROR或INSTALL_CORRUPT,则将背景设置为RecoveryUI::ERROR。
将进度条的类型设置为RecoveryUI::EMPTY,表示没有进度信息。
调用get_menu_selection函数,显示菜单并等待用户选择。该函数的参数包括一个空指针nullptr,表示不显示标题;device->GetMenuItems(),表示获取设备的菜单项;0,表示不显示菜单的起始索引;0,表示不显示菜单的结束索引;device,表示设备对象。
函数最终返回用户选择的操作,可以是Device::REBOOT、Device::SHUTDOWN或Device::REBOOT_BOOTLOADER。如果用户没有选择任何操作,则返回Device::NO_ACTION,表示采取默认操作,即根据--shutdown_after标志决定是重启还是关机。
recovery 启动流程
参考链接 | Recovery启动流程(2)---UI界面【转】-腾讯云开发者社区-腾讯云 https://www.cnblogs.com/xiaolei-kaiyuan/p/5456227.html android-ramdisk.img分析、recovery.img&boot.img执行过程 |
我们知道,当我们通过按键或者应用进入recovery模式,实质是kernel后加载recovery.img,kernel起来后执行的第一个进程就是init,此进程会读入init.rc启动相应的服务。在recovery模式中,启动的服务是执行recovery可执行文件,此文件是bootable/recovery/recovery.cpp文件生成,我们就从recovery.cpp文件开始分析。
从recovery.cpp main()中可知,进入recovery后会分析/cache/recovery/command文件,根据内容来设定显示的文字语言
SetLocale函数根据locale判断所用的字体是否属于阿拉伯语系,阿拉伯语的书写习惯是从右到左,如果是阿拉伯语系的话,就设置一个标志,后面根据这个标志决定从右到左显示文字或进度条。关于显示文字的语言通过代码即可查看,这里只简单的列出语言设置的几条主线,不贴出具体的代码(太多了)。
recovery 编译makefile
makefile路径 | build/core/Makefile |
代码 | /res 对应路径 bootable/recovery/res-xhdpi bootable/recovery/res-mdpi |
build/core/Makefile
# Otherwise, use the default medium density.
recovery_densities := ldpi
endififneq (,$(wildcard $(recovery_resources_common)-$(recovery_density)))
recovery_resources_common := $(recovery_resources_common)-$(recovery_density)
else
# recovery_resources_common := $(recovery_resources_common)-xhdpi
recovery_resources_common := $(recovery_resources_common)-mdpi
endif
recovery 图片大小
路径 | bootable/recovery/fonts |
内容 | 2*22.png 打开如图 注意要包含空余空余 |
img文件 | 编译出来的recovery.img |
ramdisk、boot.img、recovery.img之间的关系
ramdisk.img会被打包到boot.img和recovery.img中(不是同一个ramdisk.img).
ramdisk.img中比较重要的文件是"init","init.rc",其中init是system/core/init/init.c编译而来,
boot.img中ramdisk里的init.rc位于system/core/init/init.rc,
recovery.img中ramdisk里的init.rc位于bootable/recovery/etc/init.rc。
kernel加载结束以后第一个进程是执行init,init会解析init.rc文件,并起相应的服务。
由此可以知道正常开机和进入recovery模式起的进程是不同的。
感悟
recovery这个块是自己在调试低分辨率屏幕时,kernel阶段正常显示,但是recovery界面灭有显示而排查的,后面发现主要是由于lk阶段的panel_xxxx_video.h文件初始化的command有关,但是recovery的fronts中的字符库分辨率大小确实影响了显示recovery.img的背景显示。
另外在排查问题的过程中阅读别人的博客学习,但是很容易就忘记,所以就把优质博客记录下来一方面方便自己查阅,另一方面也是帮助大家过滤
相关文章:

安卓recovery流程分析(编译、界面、图片)
目录 recovery 界面菜单 recovery 界面操作 recovery 启动流程 recovery 编译makefile recovery 图片大小 ramdisk、boot.img、recovery.img之间的关系 authordaisy.skye的博客_CSDN博客-嵌入式,Qt,Linux领域博主 recovery 界面菜单 recovery 界面显示 android recoveryuse …...

唤醒手腕 2023年 B 站课程 Golang 语言详细教程笔记(更新中)
0001、1000集GO语言Flag毒誓 唤醒手腕UP猪Pig目标花费1000集进行讲解Go语言视频学习教程(有趣的灵魂,适合小白,不适合巨佬),从2023年3月19日开始,将会一直每天更新,准备在2024年5月1日之前更新…...
Qt获取屏幕(桌面)的大小或分辨率
Qt提供QDesktopWidget和QScreen两个类获取屏幕大小。Qt5开始,QDesktopWidget官方不建议使用,改为QScreen。Qt 6.0 及之后版本,QDesktopWidget 已从QtWidgets 模块中被彻底移除。 QDesktopWidget QDesktopWidget 提供了详细的位置信息&#…...

第4讲:vue内置命令(文本插值,属性绑定,v-text,v-html)
MVVM 什么是MVVM? MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。 View层: 视图层 在我们前端开发中,通常就是 DOM 层。 主要的作用是…...
vue实现自动生成路由,非手动创建,含避坑点
自动生成路由js文件:autoRouter.js let routeArr []; let baseUrl /components/settingManagement/; const content require.context(../components/settingManagement/, true, /\.vue$/); content.keys().forEach(e > {const path e.substring(e.indexOf(/…...

数据挖掘note(赵老师语录)
(一) 数据挖掘一般分为机器学习和统计学习,大数据学的课程一般是关于机器学习,我们学的浅,主要关于统计学习,示意图如下所示: 这是一个大数据时代,但是数据挖掘的利用率不足0.5%&am…...

秋招在线人才测评考什么内容?
又是一年招聘季,各大高校都会组织校园招聘,这次我们就来了解一下秋季校园招聘究竟考什么。近些年来校园秋招已经广泛采用在线测评,尤其各行业龙头大厂们,网申、在线测评、小组无领导讨论,一面二面......各类纷杂的面试…...

LeetCode算法二叉树—236. 二叉树的最近公共祖先
目录 236. 二叉树的最近公共祖先 代码: 运行结果: 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足…...

Qt事件处理
1. 事件 众所周知Qt是一个基于C的框架,主要用来开发带窗口的应用程序(不带窗口的也行,但不是主流)。我们使用的基于窗口的应用程序都是基于事件,其目的主要是用来实现回调(因为只有这样程序的效率才是最高…...

宝塔nginx搭建Ftp文件服务器
一:创建FTP 填入账号密码后,选择根目录,这个根目录就是nginx要代理的目录 二:配置nginx root的地址就是上面填的FTP根目录 三:http访问 服务器ip端口号加图片 例如我放了一个320.jp 我服务器ip是110.120.120.120 那…...

SAP和APS系统订单BOM核对(SAP配置BOM攻略九)
配置订单BOM因为要考虑历史ECN、特征语法、BOM语法,是最复杂的一个算法结果,为了摆脱这种被动的场景,博主开发了一个被动核对数据的程序来保障数据质量。 今天是APS系统上线的第三天,我们的核对程序在昨天上线,面对大量…...

ExcelServer EXCEL服务器使用- 用户、角色权限配置
Excel文件服务器搭建 搭建Excel服务器 1、登录 默认 用户名 Admin 密码 3 2、角色管理 添加修改角色 角色配置在 系统管理->角色.fexm文件夹下 可以像修改excel文件一样 修改角色 3、用户管理 添加修改用户 用户的修改在 系统管理->用户.fexm 可以像excel一样编辑用户…...

JOSEF约瑟 静态中间继电器JZY-402 JZJ-404 AC220V 触点形式两开两闭
系列型号: JZY(J)-400静态中间继电器 JZ-Y-401静态中间继电器JZ-Y-402静态中间继电器 JZ-Y-403静态中间继电器JZ-Y-404静态中间继电器 JZ-Y-405静态中间继电器JZ-Y-406静态中间继电器 JZ-Y-407静态中间继电器JZ-Y-408静态中间继电器 JZ-Y-409静态中间继电器JZ…...
C#并发编程的实现方式
一、多线程:是一种并发编程技术,它允许一个应用程序同时执行多个线程。每个线程都有自己的指令集和堆栈,可以在不同的CPU核心上并行运行,或者在一个CPU核心上通过时间片轮转的方式交替运行。多线程的主要优点是可以利用多核处理器…...

qemu源码下载和安装
1、QEMU源码下载 1、官网:https://www.qemu.org/; 2、在“Full of releases”中可以找到以往发布过的版本; 2、源码编译 # 配置命令,生成Makefile。其中--target-list指定编译哪些些架构对应的目录,默认是所有架构都编…...

计算机,软件工程,网络工程,大数据专业毕业设计选题有哪些(附源码获取)
计算机,软件工程,网络工程,大数据专业毕业设计选题有哪些?(附源码获取) ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于J…...

CyclicBarrier 、CountDownLatch 、Semaphore 的用法
1 CountDownLatch(线程计数器 ) CountDownLatch类位于java.util.concurrent 包下,利用它可以实现类似计数器的功能。比如有一个任务 A,它要等待其他 4 个任务执行完毕之后才能执行,此时就可以利用 CountDownLatch 来实…...
RestTemplate发送HTTPS请求
RestTemplate发送HTTPS请求 基础知识: Https原理与工作流程及证书校验:https://www.cnblogs.com/zjdxr-up/p/14359904.html 忽略ssl证书的方式配置: import lombok.extern.slf4j.Slf4j;import org.springframework.http.client.SimpleClien…...

图像练习-矩形4点OpenCV(01)
提取出里面最大矩形的四个顶点坐标 源图像 结果展示 代码 void getLine(std::vector<int>& data, int threshold) {for (int x 0; x < data.size(); x){if (0 data[x]){continue;}int maxValue 0, maxLoc -1, i -1;for (i x; i < data.size(); i){if …...
不同层设置不同学习率
使用预训练模型时,可能需要将 (1)预训练好的 backbone 的 参数学习率设置为较小值, (2)而backbone 之外的部分,需要使用较大的学习率。 from collections import OrderedDict import torch.nn …...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...

【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...

【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...