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

来源:互联网 发布:网易足球数据 编辑:程序博客网 时间:2024/05/17 01:13

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
intmain(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_ = 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.cppvoid 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);            //************
    .........
}}
复制代码

 

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

原创粉丝点击