Android Recovery Ui 分析

來源:互聯網
上載者:User

標籤:

Android recovery和android本質上是兩個獨立的rootfs, 只是recovery這個rootfs存在的意義就是為android這個rootfs服務,因此被解釋為Android系統的一部分。 recovery作為一個簡單的rootfs, 提供了非常有限的幾個功能,只包含了幾個簡單的庫,UI的顯示採用的是直接刷framebuffer的形式,作為android framework及app層的碼農,對這種形式相對陌生,特抽點時間梳理了一番。 首先,瀏覽一下reocvery的main函數代碼中UI相關的語句
main(int argc, char **argv) {    ......    Device* device = make_device();            ui = device->GetUI();    gCurrentUI = ui;    ui->Init();    ui->SetLocale(locale);    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()返回一個DefaultUI對象,recovery中涉及到三個UI類,三個類之間為繼承關係,分別為DefaultUI、 ScreenRecoveryUI、RecoveryUI 3、調用DefaultUI類的Init(), DefaultUI類沒有Init()方法,因此將調用它的父類ScreenRecoveryUI的Init() 4、同理,調用ScreenRecoveryUI類的SetLocale()來標識幾個比較特別的地區 5、同理,調用ScreenRecoveryUI類的SetBackground()設定初始狀態的背景圖 6、顯示recovery的主介面,即一個選擇菜單

void ScreenRecoveryUI::Init(){    gr_init();    gr_font_size(&char_width, &char_height);    text_col = text_row = 0;    text_rows = gr_fb_height() / char_height;    if (text_rows > kMaxRows) text_rows = kMaxRows;    text_top = 1;    text_cols = gr_fb_width() / char_width;    if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1;    LoadBitmap("icon_installing", &backgroundIcon[INSTALLING_UPDATE]);    backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];    LoadBitmap("icon_error", &backgroundIcon[ERROR]);    backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR];    LoadBitmap("progress_empty", &progressBarEmpty);    LoadBitmap("progress_fill", &progressBarFill);    LoadLocalizedBitmap("installing_text", &backgroundText[INSTALLING_UPDATE]);    LoadLocalizedBitmap("erasing_text", &backgroundText[ERASING]);    LoadLocalizedBitmap("no_command_text", &backgroundText[NO_COMMAND]);    LoadLocalizedBitmap("error_text", &backgroundText[ERROR]);    int i;    progressBarIndeterminate = (gr_surface*)malloc(indeterminate_frames *                                                    sizeof(gr_surface));    for (i = 0; i  0) {        installationOverlay = (gr_surface*)malloc(installing_frames *                                                   sizeof(gr_surface));        for (i = 0; i 

1、gr_init() 初始化圖形裝置,分配Pixelflinger庫渲染的記憶體

2、gr_font_size() 將字型對應的surface長寬賦值給char_width和char_height

3、LoadBitmap() 將png產生surface, 每個png圖片對應一個surface, 所有surface存放在一個數組中4、LoadLocalizedBitmap() 將地區文字所在的圖片中的text資訊根據當前的locale提取出來,產生對應的surface, 所以 surface也存放在一個數組中6、pthread_create(&progress_t, NULL, progress_thread, NULL)建立一個線程,該線程的任務是一個死迴圈,在該迴圈中不停 地檢測currentIcon以及progressBarType來決定是不是要更新進度條。7、調用RecoveryUI的Init(),初始化輸入事件處理。

void ScreenRecoveryUI::SetLocale(const char* locale) {    if (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);    }}

ScreenRecoveryUI類的SetLocale, 該函數根據locale判斷所用的字型是否屬於阿拉伯語系,阿拉伯語的書寫習慣是從右至左,如果是阿拉伯語系的話,就設定一個標誌,後面根據這個標誌決定從右至左顯示文字或進度條。SetLocale的參數locale賦值邏輯是這樣的,先從command檔案中讀取, command檔案中設定locale的命令如"--locale=zh_CN“,如果沒有傳入locale,初始化過程中會嘗試從/cache/recovery/last_locale中讀取locale, 如果該檔案也沒有,則locale不會被賦值,就預設用English.
void ScreenRecoveryUI::SetBackground(Icon icon){    pthread_mutex_lock(&updateMutex);    // Adjust the offset to account for the positioning of the    // base image on the screen.    if (backgroundIcon[icon] != NULL) {        gr_surface bg = backgroundIcon[icon];        gr_surface text = backgroundText[icon];        overlay_offset_x = install_overlay_offset_x + (gr_fb_width() - gr_get_width(bg)) / 2;        overlay_offset_y = install_overlay_offset_y +            (gr_fb_height() - (gr_get_height(bg) + gr_get_height(text) + 40)) / 2;    }    currentIcon = icon;    update_screen_locked();    pthread_mutex_unlock(&updateMutex);}
SetBackground函數比較簡潔,關鍵區段在update_screen_locked,下面我們重點分析一下。 update_screen_locked和update_progress_locked是recovery的UI部分的關鍵函數,update_screen_locked用來更新背景, update_progress_locked用來更新進度條,因為顯示的畫面會一直在更新,所以這兩個函數會在不同的地方被反覆調用
void ScreenRecoveryUI::update_screen_locked(){    draw_screen_locked();    gr_flip();}
update_screen_locked包含兩個操作,一是更新screen, 二是切換前後buffer。
void ScreenRecoveryUI::draw_screen_locked(){    draw_background_locked(currentIcon);    draw_progress_locked();    if (show_text) {        SetColor(TEXT_FILL);        gr_fill(0, 0, gr_fb_width(), gr_fb_height());        int y = 0;        int i = 0;        if (show_menu) {            SetColor(HEADER);            for (; i  y+2 && count  draw_background_locked函數的實現代碼中又出現了幾個以gr_開頭的函數,以gr_開頭的函數來自minui庫,minui庫的代碼在recovery源碼下的minui目錄下,minui提供的介面實現了圖形的描繪以及固定大小的文字顯示。gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);  /* 設定字型顏色 */  gr_fill(int x, int y, int w, int h);  /* 填充矩形地區,參數分別代表起始座標、矩形地區大小 */  gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy);  /* 填充由source指定的圖片 */  draw_background_locked函數先將整個渲染buffer填充為黑色,然後計算背景surface的長寬,文字surface的長寬,再結合fb的長寬計算出背景surface以及文字surface顯示的座標,有長寬和座標就可以調用Pixelflinger的介面在渲染buffer上進行渲染。 
void ScreenRecoveryUI::draw_progress_locked(){    if (currentIcon == ERROR) return;    if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {        draw_install_overlay_locked(installingFrame);    }    if (progressBarType != EMPTY) {        int iconHeight = gr_get_height(backgroundIcon[INSTALLING_UPDATE]);        int width = gr_get_width(progressBarEmpty);        int height = gr_get_height(progressBarEmpty);        int dx = (gr_fb_width() - width)/2;        int dy = (3*gr_fb_height() + iconHeight - 2*height)/4;        // Erase behind the progress bar (in case this was a progress-only update)        gr_color(0, 0, 0, 255);        gr_fill(dx, dy, width, height);        if (progressBarType == DETERMINATE) {            float p = progressScopeStart + progress * progressScopeSize;            int pos = (int) (p * width);            if (rtl_locale) {                // Fill the progress bar from right to left.                if (pos > 0) {                    gr_blit(progressBarFill, width-pos, 0, pos, height, dx+width-pos, dy);                }                if (pos  0) {                    gr_blit(progressBarFill, 0, 0, pos, height, dx, dy);                }                if (pos  draw_progress_locked函數的原理與 update_screen_locked函數類似, 最終是將進度條的surface輸出到渲染buffer, recovery中各個情境的畫面,就是由背景、文字、進度條的重疊,不同的是所用的surface 以及surface的座標。 recovery main函數中的UI代碼基本上已經分析過了,最後一點主菜單的顯示,就是通過上面介紹的這些介面將文字圖片顯示出來,因此就不再多講。總的來說,recovery的UI顯示部分難度不大,應用程式層調用minui庫實現了圖形的描繪以及固定大小的文字顯示,minui庫調用了Pixelflinger庫來進行渲染。 附上minui部分介面的說明,供參考
int gr_init(void);             /* 初始化圖形顯示,主要是開啟裝置、分配記憶體、初始化一些參數 */  void gr_exit(void);            /* 登出圖形顯示,關閉裝置並釋放記憶體 */    int gr_fb_width(void);         /* 擷取螢幕的寬度 */  int gr_fb_height(void);        /* 擷取螢幕的高度 */  gr_pixel *gr_fb_data(void);    /* 擷取顯示資料緩衝的地址 */  void gr_flip(void);            /* 重新整理顯示內容 */  void gr_fb_blank(bool blank);  /* 清屏 */    void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);  /* 設定字型顏色 */  void gr_fill(int x, int y, int w, int h);  /* 填充矩形地區,參數分別代表起始座標、矩形地區大小 */  int gr_text(int x, int y, const char *s);  /* 顯示字串 */  int gr_measure(const char *s);             /* 擷取字串在預設字型檔中佔用的像素長度 */  void gr_font_size(int *x, int *y);         /* 擷取當前字型檔一個字元所佔的長寬 */    void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy);  /* 填充由source指定的圖片 */  unsigned int gr_get_width(gr_surface surface);   /* 擷取圖片寬度 */  unsigned int gr_get_height(gr_surface surface);  /* 擷取圖片高度 */  /* 根據圖片建立顯示資源資料,name為圖片在mk檔案指定的相對路徑 */  int res_create_surface(const char* name, gr_surface* pSurface);  void res_free_surface(gr_surface surface);       /* 釋放資源資料 */  

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

Android Recovery Ui 分析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.