寫在前面:
本篇博文所討論的內(nèi)容主要是與大家1起討論Recovery模式本地化顯示文本的原理,和如何使用谷歌提供的recovery_l10n工具實現(xiàn)定制本地化顯示的文本。
首先我們來討論Recovery模式下本地化文本的顯示是如何實現(xiàn)的。
先看兩張圖,相信很多人都很熟習,第1張是我們恢復出廠設(shè)置操作,關(guān)機重啟進入recovery模式以后所看到的界面,第2張是通過按鍵進入recovery模式,帶有選項菜單的主界面。1般來講普通用戶正常的操作是不會看到第2個界面的,而在第1張圖片中我們看到,在綠色小機器人下面有1行字符,這行字符就是本文的關(guān)鍵。
圖1:恢復出廠設(shè)置-擦除數(shù)據(jù)
圖2:recovery模式主界面-選項菜單
其實上面這行文本內(nèi)容其實不是以字符的情勢顯示的,而是用圖片代替,以下圖:
圖3:本地化文本圖片合成
補充1下,就是說當Recovery模式下需要顯示這些文本信息的時候,會根據(jù)進入recovery模式前的系統(tǒng)語言來從上面這張圖片中截取對應(yīng)語言的文本信息,也就是說這個信息其實不是直接用C語言打印輸出到屏幕上的。
在Recovery模式下是不支持系統(tǒng)語言庫的,但是recovery中文本信息本地化又是與主系統(tǒng)當前語言環(huán)境保持同步的,那末,在recovery模式是如何與主系統(tǒng)進行交互的呢?
主系統(tǒng)與recovery通過command文件中特定的參數(shù)進行交互的。
首先來看framework/base/core/java/android/os/RecoverySystem.java中的代碼片斷:
從上面代碼告知我們,主系統(tǒng)是通過COMMAND_FILE文件的情勢與recovery進行交互,根據(jù)不同的命令行參數(shù)履行不同的操作,如系統(tǒng)升級、恢復出廠設(shè)置等。
BCB主要用來加載和啟動系統(tǒng),并且通過讀取flash中MISC分區(qū)中主系統(tǒng)和recovery的信息,并做出相應(yīng)處理。BCB既是Bootloader和Recovery的通訊接口,也是Bootloader與主系統(tǒng)的接口,為何呢?我們來了解下BCB的結(jié)構(gòu)體:
struct bootloader_message {
char command[32];
char status[32];
char recovery[1024];
};
從上面1部份我們了解到當系統(tǒng)進行恢復出廠設(shè)置操作時會將主系統(tǒng)當前的語言環(huán)境作為參數(shù)寫入/bootable/recovery/command中,而上面結(jié)構(gòu)體中的command區(qū)域就是主系統(tǒng)與recovery交互式所操作的區(qū)域,當主系統(tǒng)想要進入recovery模式時,會修改MISC分區(qū)中command區(qū)域并重啟,而Bootloader會根據(jù)command區(qū)域中的信息來決定是進入主系統(tǒng)還是recovery系統(tǒng)。
/system/core/init/signal_handler.c里的wait_for_one_process函數(shù)中有以下代碼:
android_reboot(ANDROID_RB_RESTART2, 0, "recovery")->
__reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_RESTART2, “recovery”);
因此BCB就成了主系統(tǒng)與recovery進行交互的橋梁。
當BCB加載recovery.img來啟動recovery模式時,會在recovery的initrc,kernel啟動完成后啟動第1個recovery服務(wù),也就是recovery.cpp,位于/bootable/recovery/目錄下。
在recovery.c中會首先履行get_args函數(shù)(如,get_args(&argc, &argv);),用來獲得命令行參數(shù),也就是讀取/cache/recovery/command中的命令行參數(shù)。get_args不但會獲得到命令行參數(shù)也會將獲得到的參數(shù)寫入到MISC分區(qū)中,這樣1旦在履行升級或恢復出廠設(shè)置進程中失敗,重啟以后照舊會進入recovery模式重新履行之前失敗的動作。
Recovery模式是支持command文件中特定參數(shù)的,如OPTIONS[]中的定義:
static const struct option OPTIONS[] = {
{ "send_intent", required_argument, NULL, 's' },//向intent文件中寫入數(shù)據(jù)
{ "update_package", required_argument, NULL, 'u' },//驗證ota package路徑下更新包文件
{ "wipe_data", no_argument, NULL, 'w' },//擦除data分區(qū)
{ "wipe_cache", no_argument, NULL, 'c' },//擦除cache分區(qū)
{ "show_text", no_argument, NULL, 't' },//顯示主菜單
{ "just_exit", no_argument, NULL, 'x' },//退出并重啟
{ "locale", required_argument, NULL, 'l' },//本地化
{ NULL, 0, NULL, 0 },
};
當我們恢復出廠設(shè)置重啟進入recovery模式時會首先履行recovery.cpp下main函數(shù),recovery系統(tǒng)會將/cache/recovery/command中的內(nèi)容作為命令行參數(shù)傳遞給main函數(shù):
/bootable/recovery/recovery.cpp
int arg;
while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != ⑴) {
switch (arg) {
case 'p': previous_runs = atoi(optarg); break;
case 's': send_intent = optarg; break;
case 'u': update_package = optarg; break;
case 'w': wipe_data = wipe_cache = 1; break;
case 'c': wipe_cache = 1; break;
case 't': show_text = 1; break;
case 'x': just_exit = true; break;
case 'l': locale = optarg; break;
case '?':
LOGE("Invalid command argument ");
continue;
}
}
if (locale == NULL) {
load_locale_from_cache();
}
printf("locale is [%s] ", locale);
Device* device = make_device();
ui = device->GetUI();
ui->Init();
ui->SetLocale(locale);
ui->SetBackground(RecoveryUI::NONE);
if (show_text) ui->ShowText(true);
上面getopt被用來解析命令行選項參數(shù),而getopt_long支持長選項的命令行解析,第3個參數(shù)指的就是命令行選項參數(shù)所組成的字符串,如果單個字符后面跟了1個冒號則表示該選項后面必須跟1個參數(shù),而參數(shù)的指針會復制給optarg。在上面這段代碼中,參數(shù)“l”指的就是本地化。Recovery系統(tǒng)會根據(jù)這個參數(shù)(如--local=en)來決定第1張圖中的文字對應(yīng)的時第3張圖的哪1部份的。那末我們恢復出廠設(shè)置操作的時,command中所對應(yīng)的參數(shù)是甚么模樣的呢,看下面:
--wipe_data
--locale=en
這樣的話,也就解釋了case 'l': locale = optarg; break;中變量為什么從optarg中取值了。
然后recovery會通過下面1系列的函數(shù)調(diào)用來實現(xiàn)對預制png圖片中對應(yīng)的文本信息進行截取,以下:
(bootable/recovery/screen_ui.cpp)ScreenRecoveryUI::Init()-->ScreenRecoveryUI::LoadLocalizedBitmap()-->(bootable/recovery/minui/resources.c)res_create_localized_surface();
int res_create_localized_surface(const char* name, gr_surface* pSurface) {
char resPath[256];
GGLSurface* surface = NULL;
int result = 0;
unsigned char header[8];
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
*pSurface = NULL;
snprintf(resPath, sizeof(resPath)⑴, "/res/images/%s.png", name);
resPath[sizeof(resPath)⑴] = ' 主站蜘蛛池模板: 一区二 | 激情四射综合网 | 国产3区 | 国产视频一区二区三区四区 | 欧美性大战久久久久久久蜜臀 | 99热在线播放 | 草草网站 | 视频精品一区二区三区 | 精品三级在线 | 亚洲最大成人免费视频 | 日韩欧美成 | 澳门永久av免费网站 | 国产传媒一区二区三区 | 久久精品无码一区二区三区 | 日韩欧美自拍偷拍 | 免费的黄色在线视频 | 99久久九九| www.在线播放 | 九九综合 | 国产精品日韩在线观看 | 久久91精品国产91久久跳 | 国产精品久久一区 | 国产伦精品一区二区免费 | 国产乱国产乱300精品 | 色欧美在线 | 日韩黄色在线 | 久久国产免费看 | 国产精品日韩 | 精品国产一区二区三区久久久久久 | 亚洲二区在线视频 | 秋霞色 | 日韩欧美亚洲综合 | 变态 另类 欧美 大码 日韩 | 久久成人免费网 | 日韩欧美在线视频观看 | 国产精品99久久久久久动医院 | 91精品国产乱码久久久 | 天天操夜夜撸 | 国产精品一区二区三区免费 | 成人在线视频播放 | 在线播放av网站 |