专栏首页linux驱动个人学习Recovery启动流程(2)---UI界面【转】

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

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);            //************
    .........
   
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 启动期间的内存管理之build_zonelists初始化备用内存域列表zonelists--Linux内存管理(十三)

    我们之前讲了在memblock完成之后, 内存初始化开始进入第二阶段, 第二阶段是一个漫长的过程, 它执行了一系列复杂的操作, 从体系结构相关信息的初始化慢慢向...

    233333
  • Android Recovery升级原理

    Recovery模式指的是一种可以对安卓机内部的数据或系统进行修改的模式(类似于windows PE或DOS)。也可以称之为安卓的恢复模式,在这个所谓的恢复模式...

    233333
  • liteos动态加载(十三)

    静态链接是在链接阶段将程序各模块文件链接成一个完整的可执行文件,运行时作为整体一次性加载进内存。动态加载允许用户将程序各模块编译成独立的文件而不将它们链接起来,...

    233333
  • 【干货】 知否?知否?一文彻底掌握Seaborn

    Seaborn 是基于 matplotlib 开发的高阶 Python 数据可视图库,用于绘制优雅、美观的统计图形。

    yuquanle
  • 盘一盘 Python 系列 6 - Seaborn

    Seaborn 是基于 matplotlib 开发的高阶 Python 数据可视图库,用于绘制优雅、美观的统计图形。

    用户5753894
  • python argparse模块使用

    本文由腾讯云+社区自动同步,原文地址 https://stackoverflow.club/argparse-module-in-python3/

    羽翰尘
  • GAIL(Imitating driver behavior with GAN)

    精确预测和仿真人们驾驶行为在人工智能系统中尤为重要。传统模型采用简单的参数化模型和行为克隆。论文提出了一个新的方法来解决先验分布中的连续误差问题,可以使得在存在...

    用户1908973
  • 『互联网架构』软件架构-解密电商系统商品模块业务(72)

    1.商品的资料(比方:卖什么手机,手机的一些资料) 2.商品的图片处理(拍照,ps特效等) 3.商品发布 4.商品维护(商品库存的更新,商品图片,属性的修改,促...

    IT故事会
  • 线性判别分析LDA(Linear Discriminant Analysis)

    1. 问题 之前我们讨论的PCA、ICA也好,对样本数据来言,可以是没有类别标签y的。回想我们做回归时,如果特征太多,那么会产生不相关特征引入、过度拟...

    机器学习AI算法工程
  • Enterprise Library Policy Injection Application Block 之一: PIAB Overview

    在过去的半年里,定期或者不定期地写点东西已经成为了我的一种习惯。可是最近两个月来一直忙于工作的事情一直足够的时间留给自己,虽然给自己列了很长一串写作计划,可是心...

    蒋金楠

扫码关注云+社区

领取腾讯云代金券