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);
}
....
}
-
首先新建了一個Device類的物件, Device類封裝了一些操作,包括UI的操作
-
呼叫Device類的GetUI()回傳一個RecoveryUI物件
-
呼叫ui->SetLocale(locale)設定語言,呼叫SetBackground方法設定背景圖片
-
呼叫Init()進行初始化,
-
這里的Init從代碼上看應該是ui.cpp檔案中RecoveryUI類的Init()方法,是ScreenRecoveryUI,這里我是按照ScreenRecoveryUI::Init追的代碼,其中RecoveryUI是ScreenRecoveryUI的父類,
-
顯示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); //************
.........
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/40771.html
標籤:嵌入式
