转载请注明来源:cuixiaolei的技术博客

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

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

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的主界面,即一个选择菜单

初始化

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_ = * text_cols_; //max is 6 char for 1 utf8 character.
text_ = Alloc2d(text_rows_, ml_cols_ + );
file_viewer_text_ = Alloc2d(text_rows_, ml_cols_ + );
menu_ = Alloc2d(text_rows_, ml_cols_ + );
menu_headers_wrap = Alloc2d(text_rows_, ml_cols_ + );
#else
text_ = Alloc2d(text_rows_, text_cols_ + );
file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + );
menu_ = Alloc2d(text_rows_, text_cols_ + );
#endif text_col_ = text_row_ = ;
text_top_ = ; backgroundIcon[NONE] = nullptr;
LoadBitmapArray("icon_installing", &installing_frames, &installation);
backgroundIcon[INSTALLING_UPDATE] = installing_frames ? installation[] : 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") == || // Arabic
strcmp(lang, "fa") == || // Persian (Farsi)
strcmp(lang, "he") == || // Hebrew (new language code)
strcmp(lang, "iw") == || // Hebrew (old language code)
strcmp(lang, "ur") == ) { // 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(, , , );
gr_clear();
draw_background_locked(currentIcon);            //************
    .........

}
}

此文章持续更新.......

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

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

    Recovery启动流程系列文章把recvoery目录下文件分成小块讲解,最后再以一条主线贯穿所有的内容.这篇文章主要讲解Recovery-UI的相关内容. 我们知道,当我们通过按键或者应用进入rec ...

  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. C# 引用类型的"祸害"

    前端时间刚刚弄完一个项目,终于有时间来总结与回顾了. 项目需求:给用户发送邮件,邮件分为系统邮件和个人邮件,需要按时间.未读降序排列. 一开始以为,这是一个很简单的需求,给邮件建了一个对象: clas ...

  2. 搜狐云景paas平台实践之路

    前言: 搜狐云景作为搜狐的paas平台,在2014年5月22日的云计算大会上正式发布了公测.初测,注册用户必须先申请邀请码参与公测会赠送用户100元电子券,经过实名认证之后会再赠送100电子券,目测可 ...

  3. ZOJ3772 - Calculate the Function(线段树+矩阵)

    题目大意 给定一个序列A1 A2 .. AN 和M个查询 每个查询含有两个数 Li 和Ri. 查询定义了一个函数 Fi(x) 在区间 [Li, Ri] ∈ Z. Fi(Li) = ALi Fi(Li ...

  4. 终于弄好了 homework-09

    近一周的时间,顶着编译大作业严重搁置的压力,天天搞,终于把网页动态展示的搞出来了!恩,还挺好看~ 因为是最后一次作业了,也是因为天生的完美主义强迫症,做到自己满意才放心停下来.不过,这个过程,看着同学 ...

  5. sass学习(2)——关于变量

    定义一个sass变量 可以说,变量是一个编程语言的基础.所以对于sass来说,变量肯定是浓墨重彩的其中一笔,当然函数也是.那我们如何声明定义一个sass的变量呢? 变量的符号$ 变量名称 变量的值 那 ...

  6. shell下解码url

    http://aaronw.me/static/779.html 封装了一下,有需要的拿走 function url_decode() { local url=$ echo $url | awk 'B ...

  7. 大道至简—SQLite3 使用教学

    OS X自从10.4后把SQLite这套相当出名的数据库软件,放进了作业系统工具集里.OS X包装的是第三版的SQLite,又称SQLite3.这套软件有几个特色:        软件属于公共财(pu ...

  8. CentOS 搭建LNMP服务器和LAMP服务器

    CentOS 搭建LNMP服务器 方法一:yum安装 1.更新YUM源 wget http://www.atomicorp.com/installers/atomic   #下载atomic自动更新Y ...

  9. Spring Data JPA教程, 第二部分: CRUD(翻译)

    我的Spring Data Jpa教程的第一部分描述了,如何配置Spring Data JPA,本博文进一步描述怎样使用Spring Data JPA创建一个简单的CRUD应用.该应用要求如下: pe ...

  10. Spring 的两个配置容器的讲解

    容器 是Spring框架的核心,是组件存活的地方.Spring容器使用DI管理所有组成应用系统的组件,协作组件之间建立联.而且, 这些对象简洁易懂,降低耦合性,支持重用,容易被测试. Spring提供 ...