高通recovery流程分析(编译、界面、图片)

2023-09-21 11:39:39

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_MDTP
                if (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
endif

ifneq (,$(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 打开如图用ps查看,并裁剪其中一个字符的大小是12*22像素

注意要包含空余空余

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的背景显示。

        另外在排查问题的过程中阅读别人的博客学习,但是很容易就忘记,所以就把优质博客记录下来一方面方便自己查阅,另一方面也是帮助大家过滤

更多推荐

【音视频笔记】Mediacodec+Muxer生成mp4,浏览器无法播放问题处理

文章目录背景解决过程曲线修复方案解决问题根源背景最近在测试视频录制功能时发现,AudioRecord+MediaCodec+MediaMuxer生成的MP4,PC浏览器无法播放,但是Android、Windows、Mac的播放器应用都能正常播放。虽然不禁想吐槽浏览器视频组件的容错性差,但我也意识生成的文件格式肯定也是有

Java版分布式微服务云开发架构 Spring Cloud+Spring Boot+Mybatis 电子招标采购系统功能清单

项目说明随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及审计监督要求;通过电子化平台提高招投标工作的公开性和透明性;通过电子化招投标,使得招标采购的质量更高、速度

Spring MVC 八 - 内置过滤器

SpringMVC内置如下过滤器:FormDataForwardedHeadersShallowETagCORSFormData浏览器可以通过HTTPGET或HTTPPOST提交formdata(表单数据),但是非浏览器客户端可以通过HTTPPUT、HTTPDELETE、HTTPPATCH提交表单数据。但是Servle

如何使用 Node.js和Express搭建服务器?

如何使用NodeJs搭建服务器1.准备工作1.1安装Node.js2.安装express2.1初始化package.json2.2安装express2.3Express应用程序生成器1.准备工作1.1安装Node.jsNode.js是一个开源、跨平台的JavaScript运行时环境。下载链接:Node.js官网下载建议

【数据分享】我国主要城市的商圈范围数据(免费获取\shp格式)

大家对于商圈这个概念肯定都不陌生!商圈,简单来说,就是商业聚集的区域。我国比较知名的商圈有比如北京的三里屯商圈、上海的南京东路商圈。商圈是城市商业发展的重要体现,一个城市的商圈越多、商圈范围越大、商圈能级越高,代表这个城市的商业越发达!商圈的概念也越来越深入人心,比如在大众点评上可以以商圈(商区)为规则进行店铺搜索,比

【Redis】Redis实现分布式锁

【Redis】Redis常见面试题(1)文章目录【Redis】Redis常见面试题(1)1.为什么要用分布式锁2.Redis如何实现分布式锁3.Redis接受多个请求模拟演示4.使用Redis实现分布式锁会存在什么问题4.1一个锁被长时间占用4.2锁误删【Redis】Redis常见面试题(1)1.为什么要用分布式锁之前

Pandas 数据变形和模型分析

数据概念数据比对在本练习中,我们使用灵活的比较技术对不同的DataFrame进行比较importpandasaspdimportrandomrandom.seed(123)list1=[['A']*3,['B']*5,['C']*7]charlist=[xforsublistinlist1forxinsublist]r

(vue2).sync修饰符、ref和$refs、$nextTick、自定义指令、插槽

.sync修饰符实现子组件和父组件数据的双向绑定,简化代码prop属性名,可以自定义,非固定value本质:属性名和@update:属性名的合写<BaseDialog:value="isShow"@update="isShow=$event">//等价于<BaseDialogv-model="isShow=$event

node.js

前端工程化:开发项目直到上线,过程中集成的所有工具和技术Node.js是独立执行JavaScript代码的环境Node.js环境比浏览器环境中的JS少了BOM和DOMfs模块-读写文件模块:类型插件,封装了方法/属性fs模块:封装了与本机文件系统进行交互的方法/属性语法:加载fs模块对象写入文件内容读取文件内容Comm

自定义指令

一,原生指令v-bind:属性名="变量名"v-on:事件名="函数名"缩写模式::属性名="变量名"@事件名="函数名"示例:<inputtype="text"v-bind:disabled="isDisabled"v-on:change="change"/><inputtype="text":disabled="i

「工具|数据接口」免费公开的REST API & 如何借助github搭建自己的fake API接口

本文主要介绍日常开发、测试、教学或者分享中,可能遇到的模拟数据问题。分享免费开发的测试数据接口,以及如何利用github快速搭建定制化的接口数据,避免使用真实数据的风险以及自己现编数据的麻烦。文章目录一、场景说明二、免费公开的FakeRESTAPI:jsonplaceholder三、借助GitHub和MyJSONSer

热文推荐