首页 技术 正文
技术 2022年11月15日
0 收藏 690 点赞 3,858 浏览 5735 个字

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

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

bootable/recovery/recovery.cppint
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.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); //************
    ......... }
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,497
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,910
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,744
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,497
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,135
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,298