Android recover文字显示

Posted rootshaw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)

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
具体操作可以看

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

以上是关于Android recover文字显示的主要内容,如果未能解决你的问题,请参考以下文章

Android Place自动填充片段:无法设置文字

在android中显示隐藏片段

Android片段不会显示

带有片段的 Android Up 按钮未显示完整片段

Android:RecyclerView 不显示片段中的列表项

Android 片段未显示在应用程序中