天天看點

android recovery ui,Android Recovery Ui 分析

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);

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);

unsigned int gr_get_width(gr_surface surface);

unsigned int gr_get_height(gr_surface surface);

int res_create_surface(const char* name, gr_surface* pSurface);

void res_free_surface(gr_surface surface);