Android13 Virtual A/B OTA升级速度优化

750 阅读3分钟

在Android13 Virtual A/B OTA升级中,不管是全量包还是差分包升级都要20分钟以上,在一些应用场景中很影响使用体验。本文对Virtual A/B OTA升级速度的提升做了些探索。

在升级过程中不执行DexOpt

通过升级过程的log:

09-11 14:46:39.907   971   971 I update_engine: [INFO:subprocess.cc(98)] Running "/postinstall/system/bin/otapreopt_script 1 3"

09-11 14:51:57.815   971   971 I update_engine: [INFO:subprocess.cc(156)] Subprocess output:
09-11 14:51:57.815   971   971 I update_engine: Complete or error.

发现在等待otapreopt_script执行完毕时就花了5分钟。
原因是在OTA升级阶段进行DexOpt:
juejin.cn/post/739743…

可以在编译配置文件中找到``AB_OTA_POSTINSTALL_CONFIG`的配置,并注释掉:

AB_OTA_POSTINSTALL_CONFIG += \
     RUN_POSTINSTALL_system=true \
     POSTINSTALL_PATH_system=system/bin/otapreopt_script \
     FILESYSTEM_TYPE_system=$(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE) \
     POSTINSTALL_OPTIONAL_system=true

或则在制作OTA升级包的命令中带入'--skip_postinstall`参数,如:

out/host/linux-x86/bin/ota_from_target_files \
 --block \
 --skip_postinstall \
 -p out/host/linux-x86 \
 -k build/target/product/security/releasekey \
 -v \
 target_files.zip \
 ota.zip

经验证,去掉otapreopt_script步骤可以节省5分钟,且升级成功。

关掉vabc(Virtual A/B Compression)

在log中发现另一个耗时的操作如下:

09-12 15:51:46.365  1183  1183 I update_engine: [INFO:delta_performer.cc(116)] Completed 0/? operations, 16384/1585173214 bytes downloaded (0%), overall progress 0%
09-12 15:52:16.840  1183  1183 I update_engine: [INFO:delta_performer.cc(116)] Completed 60/1100 operations (5%), 49233920/1585173214 bytes downloaded (3%), overall progress 3%
......
09-12 16:07:05.744  1183  1183 I update_engine: [INFO:delta_performer.cc(116)] Completed 1096/1100 operations (99%), 1581465600/1585173214 bytes downloaded (99%), overall progress 98%
09-12 16:07:08.161  1183  1183 I update_engine: [INFO:delta_performer.cc(116)] Completed 1100/1100 operations (100%), 1585173214/1585173214 bytes downloaded (100%), overall progress 100%

全量升级中,delta_performer.cc(116)用掉了15分钟 可看到,整个升级过程被分成了1106个operations, 大约每秒执行一个operations, 升级过程中写数据的速度大概是1.5MB/s。 是否可以通过调大每个operations的数据块的大小,减少写分区次数来提升写数据的速度。

涉及的源码: system/update_engine/payload_consumer/delta_performer.cc

bool DeltaPerformer::Write(const void* bytes, size_t count, ErrorCode* error) {
   while (next_operation_num_ < num_total_operations_) {
    switch (op.type()) {
      case InstallOperation::REPLACE:
        op_result = PerformReplaceOperation(op);
        break;

    next_operation_num_++;
    UpdateOverallProgress(false, "Completed ");
}

每个operations的数据块的大小,在FullUpdateGenerator中确定: system/update_engine/payload_generator/full_update_generator.cc:

bool FullUpdateGenerator::GenerateOperations()
  size_t full_chunk_size;
  //决定chunk_size
  if (config.hard_chunk_size >= 0) {
    full_chunk_size = std::min(static_cast<size_t>(config.hard_chunk_size),
                               config.soft_chunk_size);
  }

  size_t chunk_blocks = full_chunk_size / config.block_size;
  size_t max_threads = diff_utils::GetMaxThreads();
  LOG(INFO) << "Compressing partition " << new_part.name << " from "
            << new_part.path << " splitting in chunks of " << chunk_blocks
            << " blocks (" << config.block_size << " bytes each) using "
            << max_threads << " threads";

通过修改代码,把full_chunk_size由原来的2MB改为20MB或整个目标分区的大小,operations数量也相应减少了,但升级数据没有差别。说明影响升级速度的不是写分区的次数。

查看ota_from_target_files命令的help信息有个--disable_vabc选项,经测试,制作OTA升级包时加上--disable_vabc --skip_postinstall最终OTA升级时间控制在6分钟以内:

out/host/linux-x86/bin/ota_from_target_files \
 --block \
 --disable_vabc \
 --skip_postinstall \
 -p out/host/linux-x86 \
 -k build/target/product/security/releasekey \
 -v \
 target_files.zip \
 ota.zip

经源码分析,--disable_vabc后,在写升级数据时不走VABCPartitionWriter而是走PartitionWriter

总结

在制作OTA升级包时加上--disable_vabc --skip_postinstall最终OTA升级时间控制在6分钟以内。

遗留问题

VABCPartitionWriterPartitionWriter有什么区别,为什么花费的时间差这么多?