在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分钟以内。
遗留问题
VABCPartitionWriter
和PartitionWriter
有什么区别,为什么花费的时间差这么多?