Android recover文字显示

时人不识凌云木,直待凌云始道高。这篇文章主要讲述Android recover文字显示相关的知识,希望能为你提供帮助。

参考:
Recovery模式下的文本显示
如何修改Recovery的字符串资源
Android recovery UI实现分析
Recovery模式下的文本显示
平台 android版本 内核版本
rtd1619 9.0 4.9.1
源码路径:android/bootable/recovery
需求:
选择简体中文的情况下,但在ota升级界面文字显示为 繁体。需要调整回来思路:
1.recovery 所匹配的文字并非是根据语言国家来更改res/xml下的文本文件,而是一个包含各种语言的文本图片 (bootable/recovery/res-hdpi/images/installing_text.png)
Android recover文字显示

文章图片

2.在制作该文本png图片时候,会记录每种语言每段的信息,(locale,high,width)locale即(语言-国家)的信息
3.在进行recovery 时候,会传入android 环境下的locale ,如果传入的locale和解析png图片的locale相匹配这将这段绘制到surface

  • UI加载入口
    recover 和bootcode一样是一个简单的rootfs.使用surface直接刷framebuffer 更改界面,先查看 recovery.cpp 的main入口
int main(int argc, char **argv) { // We don\'t have logcat yet under recovery; so we\'ll print error on screen and // log to stdout (which is redirected to recovery.log) as we used to do. android::base::InitLogging(argv, & UiLogger); ... ... ... while ((arg = getopt_long(args_to_parse.size(), args_to_parse.data(), "", OPTIONS, & option_index)) != -1) {... case \'l\': locale = optarg; //从参数中获取local “语言+国家”的形式 } }

locale就是我们本文的关键
Device* device = make_device(); if (android::base::GetBoolProperty("ro.boot.quiescent", false)) { printf("Quiescent recovery mode.\\n"); ui = new StubRecoveryUI(); } else { ui = device-> GetUI(); if (!ui-> Init(locale)) { printf("Failed to initialize UI, use stub UI instead.\\n"); ui = new StubRecoveryUI(); } ... // Set background string to "installing security update" for security update, // otherwise set it to "installing system update". ui-> SetSystemUpdateText(security_update); //设置是否为安全更新 }

这里又将locale 传入UI对象
  • UI对象查找png文件
    源文件 screen_ui.cpp
bool ScreenRecoveryUI::Init(const std::string& locale) { RecoveryUI::Init(locale); ... LoadBitmap("icon_error", & error_icon); LoadBitmap("progress_empty", & progressBarEmpty); LoadBitmap("progress_fill", & progressBarFill); LoadBitmap("stage_empty", & stageMarkerEmpty); LoadBitmap("stage_fill", & stageMarkerFill); installing_text = nullptr; //这个即我所需要的 LoadLocalizedBitmap("erasing_text", & erasing_text); LoadLocalizedBitmap("no_command_text", & no_command_text); LoadLocalizedBitmap("error_text", & error_text); ... } ... // Choose the right background string to display during update. void ScreenRecoveryUI::SetSystemUpdateText(bool security_update) { if (security_update) { LoadLocalizedBitmap("installing_security_text", & installing_text); } else { LoadLocalizedBitmap("installing_text", & installing_text); //加载图片 } Redraw(); } ... void ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, GRSurface** surface) { int result = res_create_localized_alpha_surface(filename, locale_.c_str(), surface); }

  • 加载,分析png图片所需要的段
nt res_create_localized_alpha_surface(const char* name, const char* locale, GRSurface** pSurface) { ... printf(" create surface by native locale area %s\\n", locale); PngHandler png_handler(name); // 根据installing_text名字加载png if (!png_handler) return png_handler.error_code(); if (png_handler.channels() != 1) { return -7; }png_structp png_ptr = png_handler.png_ptr(); //获取png每段的信息 png_uint_32 width = png_handler.width(); png_uint_32 height = png_handler.height(); for (png_uint_32 y = 0; y < height; ++y) { std::vector< unsigned char> row(width); png_read_row(png_ptr, row.data(), nullptr); int w = (row[1] < < 8) | row[0]; int h = (row[3] < < 8) | row[2]; __unused int len = row[4]; char* loc = reinterpret_cast< char*> (& row[5]); //在png格式中第五段是locale信息(语言_国家) printf(" create surface name %20s\\n", name); //自己加的log信息 printf(" create surface locale %s\\n", locale); printf(" create surface loc %s\\n", loc); //matches_locale()即用来匹配传入的locale 信息 if (y + 1 + h > = height || matches_locale(loc, locale)) { printf("res_create_localized_alpha_surface%20s: %s (%d x %d @ %d)\\n", name, loc, w, h, y); GRSurface* surface = malloc_surface(w * h); if (!surface) { return -8; } //加载符合的数据到surface surface-> width = w; surface-> height = h; surface-> row_bytes = w; surface-> pixel_bytes = 1; for (int i = 0; i < h; ++i, ++y) { png_read_row(png_ptr, row.data(), nullptr); memcpy(surface-> data + i * w, row.data(), w); }*pSurface = surface; break; }for (int i = 0; i < h; ++i, ++y) { png_read_row(png_ptr, row.data(), nullptr); } }return 0; }

这里需要看自身的log信息看png的locale信息
比如这里我的设置中文简体情况为:
png locale: zh_CN
传入的 locale:zh-CN
这里有个问题就是:在解析台湾字段时段为
png locale :zh //看备注
所以直接匹配到了繁体
所以我们需要更改匹配规则
  • 如何比较locale信息
index 52ab60b..b5cc62f 100644 --- a/minui/resources.cpp +++ b/minui/resources.cpp @@ -397,15 +397,22 @@ bool matches_locale(const std::string& prefix, const std::string& locale) { // match the locale string without the {script} section. // For instance, prefix == "en" matches locale == "en-US", prefix == "sr-Latn" matches locale // == "sr-Latn-BA", and prefix == "zh-CN" matches locale == "zh-Hans-CN". +// prefix == "zh_CN" matches locale == "zh-Hans-CN". if (android::base::StartsWith(locale, prefix)) { return true; } -size_t separator = prefix.find(\'-\'); +size_t separator = prefix.find(\'_\'); if (separator == std::string::npos) { + return false; } -std::regex loc_regex(prefix.substr(0, separator) + "-[A-Za-z]*" + prefix.substr(separator)); +if( prefix.substr(separator+1).empty()){ +return false; +}+std::regex loc_regex(prefix.substr(0, separator) + "-[A-Za-z]*" + prefix.substr(separator+1)); return std::regex_match(locale, loc_regex); }

  • 以上就是修改内容
备注
  • 如何自己生成png图片
    在android 下面已经有源码 直接生成apk,再有apk生成png
android/bootable/recovery/tools/recovery_l10n
具体操作可以看
【Android recover文字显示】https://www.cnblogs.com/jianggest/p/recovery_string.html
  • c++ 的std::regex 类需要学习
  • png 数据分析 需要学习
PngHandler::PngHandler(const std::string& name) : error_code_(0), png_fp_(nullptr, fclose) { std::string res_path = android::base::StringPrintf("/res/images/%s.png", name.c_str()); png_fp_.reset(fopen(res_path.c_str(), "rbe")); if (!png_fp_) { error_code_ = -1; return; }unsigned char header[8]; size_t bytesRead = fread(header, 1, sizeof(header), png_fp_.get()); if (bytesRead != sizeof(header)) { error_code_ = -2; return; }if (png_sig_cmp(header, 0, sizeof(header))) { error_code_ = -3; return; }png_ptr_ = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (!png_ptr_) { error_code_ = -4; return; }info_ptr_ = png_create_info_struct(png_ptr_); if (!info_ptr_) { error_code_ = -5; return; }if (setjmp(png_jmpbuf(png_ptr_))) { error_code_ = -6; return; }png_init_io(png_ptr_, png_fp_.get()); png_set_sig_bytes(png_ptr_, sizeof(header)); png_read_info(png_ptr_, info_ptr_); int color_type; int bit_depth; png_get_IHDR(png_ptr_, info_ptr_, & width_, & height_, & bit_depth, & color_type, nullptr, nullptr, nullptr); channels_ = png_get_channels(png_ptr_, info_ptr_); if (bit_depth == 8 & & channels_ == 3 & & color_type == PNG_COLOR_TYPE_RGB) { // 8-bit RGB images: great, nothing to do. } else if (bit_depth < = 8 & & channels_ == 1 & & color_type == PNG_COLOR_TYPE_GRAY) { // 1-, 2-, 4-, or 8-bit gray images: expand to 8-bit gray. png_set_expand_gray_1_2_4_to_8(png_ptr_); } else if (bit_depth < = 8 & & channels_ == 1 & & color_type == PNG_COLOR_TYPE_PALETTE) { // paletted images: expand to 8-bit RGB.Note that we DON\'T // currently expand the tRNS chunk (if any) to an alpha // channel, because minui doesn\'t support alpha channels in // general. png_set_palette_to_rgb(png_ptr_); channels_ = 3; } else { fprintf(stderr, "minui doesn\'t support PNG depth %d channels %d color_type %d\\n", bit_depth, channels_, color_type); error_code_ = -7; } }


    推荐阅读