安卓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 …...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...