Recovery啟動流程(2)---UI界面【轉】

来源:https://www.cnblogs.com/linhaostudy/archive/2019/09/19/11549332.html
-Advertisement-
Play Games

Recovery啟動流程系列文章把recvoery目錄下文件分成小塊講解,最後再以一條主線貫穿所有的內容。這篇文章主要講解Recovery UI的相關內容。 我們知道,當我們通過按鍵或者應用進入recovery模式,實質是kernel後載入recovery.img,kernel起來後執行的第一個進程 ...


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

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • tc 是linux 內置的命令;使用man pages 查看 我們看到,其功能為 show / manipulate traffic control settings,可對操作系統進行流量控制; netem 與 tc: netem 是 Linux 2.6 及以上內核版本提供的一個網路模擬功能模塊。該 ...
  • 以下只說明各指令的基本用法,若需詳細說明,請用man去讀詳細的manual。[Cygwin通常沒有安裝 man相關的文件,所以沒有man功能] 1.關於文件/目錄處理的指令: 1.1 ls 這是最基本的文件指令。ls的意義為“list”,也就是將某一個目錄下的內容顯示出來。如果你在ls指令後 沒有跟 ...
  • linux centos 6安裝方法 前提需要: 1, centos6的鏡像文件 2,VMware 提前安裝 註: "獲取鏡像" 阿裡開源系統,此處可下載其他的 1.Ubuntu 2.Susa 3.Centos all 4. 。。。 步驟: 1. 創建 2. 安裝方式選擇 3. 系統選擇 4. 虛擬 ...
  • 大家好! 我是一名Linux小白,有幸來到馬哥教育這個大家庭與各位同學在未來的五個月里一起學習Linux技術!儘管Linux對於剛接觸到的新手會很難,但是我知道痛苦只是暫時的,滿路荊棘的後面必是明亮寬廣的大海! 在學習過程中我將堅持做到三個“做到”! 1.做到聽每節課時都做隨堂筆記! 2.做到將老師 ...
  • 學習《shell腳本學習指南》一書 一個Shell腳本的典型的開發周期: 直接在命令行上測試 找到能夠完成工作的適當的語法 將它們放進一個獨立的腳本文件里 為該腳本設置執行許可權 直接使用該腳本 ...
  • 排名不分先後。 學海無涯苦作舟。 博客: 1.slmba:LINUX博客原創大牛 2.edsionte's TechBlog:Linuxer (他的友情鏈接中還有一堆Linuxer,被公司屏蔽進不去。。) 3.Tommy_wxie:專註Linux學習,有原創也有轉發 4.JeanCheng:linu ...
  • 組件 Kubernetes 1.14.2 Docker 18.09.6-ce Etcd 3.3.13 Flanneld 0.11.0 基礎環境設置 192.168.11.188 k8s-master 192.168.11.189 k8s-node1192.168.11.190 k8s-node2 設 ...
  • 系統啟動時需要載入的配置文件 /etc/profile、/root/.bash_profile/etc/bashrc、/root/.bashrc/etc/profile.d/*.sh、/etc/profile.d/lang.sh/etc/sysconfig/i18n、/etc/rc.local(/e ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...