Recovery启动流程系列文章把recvoery目录下文件分成小块讲解,最后再以一条主线贯穿所有的内容。这篇文章主要讲解Recovery-UI的相关内容。

我们知道,当我们通过按键或者应用进入recovery模式,实质是kernel后加载recovery.img,kernel起来后执行的第一个进程就是init,此进程会读入init.rc启动相应的服务。在recovery模式中,启动的服务是执行recovery可执行文件,此文件是bootable/recovery/recovery.cpp文件生成,我们就从recovery.cpp文件开始分析。

bootable/recovery/recovery.cpp

int
main(int argc, char **argv) { ....
Device* device = make_device();
ui = device->GetUI();
gCurrentUI = ui; ui->SetLocale(locale);
ui->Init(); ui->SetBackground(RecoveryUI::NONE);
if (show_text) ui->ShowText(true);
....
if (status != INSTALL_SUCCESS || ui->IsTextVisible()) {
prompt_and_wait(device, status);
}
.... }
  1. 首先新建了一个Device类的对象, Device类封装了一些操作,包括UI的操作

  2. 调用Device类的GetUI()返回一个RecoveryUI对象

  3. 调用ui->SetLocale(locale)设置语言,调用SetBackground方法设置背景图片

  4. 调用Init()进行初始化。

  5. 这里的Init从代码上看应该是ui.cpp文件中RecoveryUI类的Init()方法,是ScreenRecoveryUI,这里我是按照ScreenRecoveryUI::Init追的代码。其中RecoveryUI是ScreenRecoveryUI的父类。

  6. 显示recovery的主界面,即一个选择菜单

实现头部显示和列表项device.h

static const char* MENU_ITEMS[] = {
"Reboot system now",
"Apply update from ADB",
"Wipe data/factory reset",
"Wipe cache partition",
"Reboot to bootloader",
"Power off",
"View recovery logs",
"Apply update from sdcard",
"Apply update from usbotg",
"Security unlock",
"Download secure info",
"Download hwc info",
"Apply OTAconfig update from sdcard",
"Apply OTAconfig update from usbotg",
"Apply OTAconfig update from usbotg path", NULL,
}; static const Device::BuiltinAction MENU_ACTIONS[] = {
Device::REBOOT,
Device::APPLY_ADB_SIDELOAD,
Device::WIPE_DATA,
Device::WIPE_CACHE,
Device::REBOOT_BOOTLOADER,
Device::SHUTDOWN,
Device::VIEW_RECOVERY_LOGS,
Device::APPLY_SDCARD,
Device::APPLY_USB,
Device::SECURE_UNLOCK,
Device::DOWNLOAD_SECURE_INFO,
Device::DOWNLOAD_HWC_INFO,
Device::APPLY_OTACONFIG_EXT,
Device::APPLY_OTACONFIG_USB,
Device::APPLY_OTACONFIG_USB_PATH, //Device::MOUNT_SYSTEM,
};
void ScreenRecoveryUI::Init() {
gr_init(); //初始化图形设备,分配Pixelflinger库渲染的内存 gr_font_size(&char_width, &char_height);
text_rows_ = gr_fb_height() / char_height;
text_cols_ = gr_fb_width() / char_width; #ifdef SUPPORT_UTF8_MULTILINGUAL
int ml_cols_ = 6 * text_cols_; //max is 6 char for 1 utf8 character.
text_ = Alloc2d(text_rows_, ml_cols_ + 1);
file_viewer_text_ = Alloc2d(text_rows_, ml_cols_ + 1);
menu_ = Alloc2d(text_rows_, ml_cols_ + 1);
menu_headers_wrap = Alloc2d(text_rows_, ml_cols_ + 1);
#else
text_ = Alloc2d(text_rows_, text_cols_ + 1);
file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + 1);
menu_ = Alloc2d(text_rows_, text_cols_ + 1);
#endif text_col_ = text_row_ = 0;
text_top_ = 1; backgroundIcon[NONE] = nullptr;
LoadBitmapArray("icon_installing", &installing_frames, &installation);
backgroundIcon[INSTALLING_UPDATE] = installing_frames ? installation[0] : nullptr;
backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
LoadBitmap("icon_error", &backgroundIcon[ERROR]); //LoadBitmap() 将png生成surface, 每个png图片对应一个surface, 所有surface存放在一个数组中
backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR]; LoadBitmap("icon_recovery", &backgroundIcon[RECOVERY]);
LoadBitmap("progress_empty", &progressBarEmpty);
LoadBitmap("progress_fill", &progressBarFill);
LoadBitmap("stage_empty", &stageMarkerEmpty);
LoadBitmap("stage_fill", &stageMarkerFill); /* add for AT&T recovery update install UI begin */
#ifdef TARGET_ATT_RECOVERY_UI
LoadBitmap("icon_attinstalling", &backgroundIcon[ATT_INSTALLING_UPDATE]);
LoadBitmap("progress_attempty", &progressBarEmpty_ATT);
LoadBitmap("progress_attfill", &progressBarFill_ATT);
LoadLocalizedBitmap("installing_atttext", &backgroundText[ATT_INSTALLING_UPDATE]); //LoadLocalizedBitmap() 将区域文字所在的图片中的text信息根据当前的locale提取出来,生成对应的surface, 所有
surface也存放在一个数组中
#endif
/* add for AT&T recovery update install UI end */ LoadLocalizedBitmap("installing_text", &backgroundText[INSTALLING_UPDATE]);
LoadLocalizedBitmap("erasing_text", &backgroundText[ERASING]);
LoadLocalizedBitmap("no_command_text", &backgroundText[NO_COMMAND]);
LoadLocalizedBitmap("error_text", &backgroundText[ERROR]); pthread_create(&progress_thread_, nullptr, ProgressThreadStartRoutine, this); //创建一个线程,在该循环中不停地检测currentIcon以及progressBarType来决定是不是要更新进度条。
RecoveryUI::Init(); //初始化RecoveryUI类
}
bootable/recovery/minui/ui.cpp

void RecoveryUI::Init() {
ev_init(InputCallback, this); ev_iterate_available_keys(std::bind(&RecoveryUI::OnKeyDetected, this, std::placeholders::_1)); pthread_create(&input_thread_, nullptr, InputThreadLoop, nullptr);
}

通过RecoveryUI::Init(); 调用events.cpp文件,界面和按键/触摸联系在一起了,后面会用单独的文章介绍recovery按键和触屏的相关内容。

下面介绍几个常用的函数

void ScreenRecoveryUI::SetLocale(const char* new_locale) {
if (new_locale) {
this->locale = new_locale;
char* lang = strdup(locale);
for (char* p = lang; *p; ++p) {
if (*p == '_') {
*p = '\0';
break;
}
} // A bit cheesy: keep an explicit list of supported languages
// that are RTL.
if (strcmp(lang, "ar") == 0 || // Arabic
strcmp(lang, "fa") == 0 || // Persian (Farsi)
strcmp(lang, "he") == 0 || // Hebrew (new language code)
strcmp(lang, "iw") == 0 || // Hebrew (old language code)
strcmp(lang, "ur") == 0) { // Urdu
rtl_locale = true;
}
free(lang);
} else {
new_locale = nullptr;
}
}

从recovery.cpp main()中可知,进入recovery后会分析/cache/recovery/command文件,根据内容来设定显示的文字语言

SetLocale函数根据locale判断所用的字体是否属于阿拉伯语系,阿拉伯语的书写习惯是从右到左,如果是阿拉伯语系的话,就设置一个标志,后面根据这个标志决定从右到左显示文字或进度条。关于显示文字的语言通过代码即可查看,这里只简单的列出语言设置的几条主线,不贴出具体的代码(太多了)。

g_ml_str[] (mi_string.h)-> ml_string_fetch() (multilingual.c)

ml_set_language (multilingual.c) -> ml_select() (recovery.cpp) -> prompt_and_wait() (recovery.cpp) -> main() (recovery.cpp)

SetBackground函数比较简洁,关键部分在update_screen_locked。

update_screen_locked 和update_progress_locked是recovery的UI部分的关键函数,update_screen_locked用来更新背 景, update_progress_locked用来更新进度条,因为显示的画面会一直在更新,所以这两个函数会在不同的地方被反复调用

void ScreenRecoveryUI::SetBackground(Icon icon) {
pthread_mutex_lock(&updateMutex); currentIcon = icon;
update_screen_locked(); pthread_mutex_unlock(&updateMutex);
}
void ScreenRecoveryUI::update_screen_locked() {
draw_screen_locked();
gr_flip();
}
void ScreenRecoveryUI::draw_screen_locked() {
if (!show_text) {
draw_background_locked(currentIcon); //************ 有一个bug因为此行没有,导致SetBackground函数无法更换背景图片
draw_progress_locked();
} else {
gr_color(0, 0, 0, 255);
gr_clear();
draw_background_locked(currentIcon); //************
    ......... }
}

Recovery启动流程(2)---UI界面【转】的更多相关文章

  1. Recovery启动流程(2)---UI界面

    转载请注明来源:cuixiaolei的技术博客 Recovery启动流程系列文章把recvoery目录下文件分成小块讲解,最后再以一条主线贯穿所有的内容.这篇文章主要讲解Recovery-UI的相关内 ...

  2. Recovery启动流程(3)--recovery.cpp分析

    转载请注明来源:cuixiaolei的技术博客 这篇文章主要通过分析高通recovery目录下的recovery.cpp源码,对recovery启动流程有一个宏观的了解.MTK和高通的recovery ...

  3. Recovery启动流程--recovery.cpp分析

    这篇文章主要通过分析高通recovery目录下的recovery.cpp源码,对recovery启动流程有一个宏观的了解. 当开机以后,在lk阶段,如果是recovery,会设置boot_into_r ...

  4. Recovery启动流程(1)--- 应用层到开机进入recovery详解

    转载请注明来源:cuixiaolei的技术博客 进入recovery有两种方式,一种是通过组合键进入recovery,另一种是上层应用设置中执行安装/重置/清除缓存等操作进行recovery.这篇文档 ...

  5. 小记--------CDH版本启动cloudera manager UI界面

    首先需要启动mysql源数据库 server所在服务器的路径:/opt/cm-5.14.0/etc/cloudera-scm-server 下 查看配置文件: db.properties   查看my ...

  6. C#/.NET基于Topshelf创建Windows服务的守护程序作为服务启动的客户端桌面程序不显示UI界面的问题分析和解决方案

    本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...

  7. (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序

    每次使用 Visual Studio 的模板创建一个 UWP 程序,我们会在项目中发现大量的项目文件.配置.应用启动流程代码和界面代码.然而这些文件在 UWP 程序中到底是如何工作起来的? 我从零开始 ...

  8. (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序

    每次使用 Visual Studio 的模板创建一个 UWP 程序,我们会在项目中发现大量的项目文件.配置.应用启动流程代码和界面代码.然而这些文件在 UWP 程序中到底是如何工作起来的? 我从零开始 ...

  9. 【Android UI设计与开发】第05期:引导界面(五)实现应用程序只启动一次引导界面

    [Android UI设计与开发]第05期:引导界面(五)实现应用程序只启动一次引导界面 jingqing 发表于 2013-7-11 14:42:02 浏览(229501) 这篇文章算是对整个引导界 ...

随机推荐

  1. 敏捷之旅--携程Scrum Master 新官上任三把火?

      随着敏捷在国内的推行,越来越多的公司和组织开始使用敏捷领导团队. 敏捷团队如雨后春笋之势涌现. 敏捷教练的团队也越来越壮大.   原先只需要一个敏捷教练就能搞定,但是随着团队越来越多,我们难免会将 ...

  2. Vue+ElementUI项目使用webpack输出MPA

    目录 Vue+ElementUI项目使用webpack输出MPA 一. 需求分析 二. 原方案分析 三. 多页面改造3步走 四. 小结 Vue+ElementUI项目使用webpack输出MPA 示例 ...

  3. python 33 多进程(一)

    目录 多进程 1. 进程创建的两种方式 multiprocessing 2. 进程pid (process id) 3. 验证进程之间的空间隔离 4. 进程对象join方法 5. 进程对象其他属性 6 ...

  4. Linux--进程管理--06

    1.操作系统的基础 调用:kernel通过给应用程序提供system call的方式来提供硬件资源: 注意:应用程序也包括库文件 库文件是运行在ring0上的一段程序代码,不对客户直接提供应用 2.程 ...

  5. MySQL 5.7 的安装历程

    mysql5.7零基础入门级的安装教程: 安装环境:Windows 10, 64 位(联想拯救者R720) 安装版本:mysql-5.7.25-winx64 一.下载 1.进入官网 首先,下载MySQ ...

  6. Unity3D 基于ShadowMap的平滑硬阴影

    前言 传统的ShadowMap在明暗边缘处都会有很难看的锯齿,因此一般得到的结果会比较难看,常规的解决办法都会在使用ShadowMap渲染阴影的时候通过背面剔除把这种缺陷隐藏掉,最后剩下一个影子.但是 ...

  7. 【selenium】- webdriver常见元素定位(下)

    本文由小编根据慕课网视频亲自整理,转载请注明出处和作者. 1.table 表格如下: 使用firebug查看: 代码实现: 1)显示出表格所有内容 2)显示表格某个特定的数值 自动化测试框架: 关键字 ...

  8. hdu-6681 Rikka with Cake

    题目链接 hdu-6681 Problem Description Rikka's birthday is on June 12th. The story of this problem happen ...

  9. E-MAZE_2019牛客暑期多校训练营(第二场)

    题意 给出n行m列的迷宫0可走1不可走,有两个操作,操作1变换点(a,b)的值,操作2查询(1,a)到(n,b)的方案数 题解 设\(F[i][j]\)为第i-1行到达第i行第j列的方案数,若点\(( ...

  10. 洛谷P1196[NOI2002]银河英雄传说-并查集扩展

    银河英雄传说 题意:在并查集的基础上,还要求出同一集合的两个点的距离 这道题用并查集自己是知道的,但是竟然可以这么骚的操作. 下面转自大佬的查详细题解 初见这道题,首先想到的方法当然是直接模拟,模拟每 ...