Android11.0 OTA差分包升级失败kDownloadStateInitializationError

Posted framework-coder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android11.0 OTA差分包升级失败kDownloadStateInitializationError相关的知识,希望对你有一定的参考价值。

AB_OTA升级模式开启条件下(MTK_AB_OTA_UPDATER=y),进行线刷验证OTA升级。

1.制作差分包相关参数说明

 -b 过时的。 
 -k 签名所使用的密钥 
 -i 生成增量OTA包时使用此选项。后面我们会用到这个选项来生成OTA增量包。 
 -w 是否清除userdata分区 
 -n 在升级时是否不检查时间戳,缺省要检查,即缺省情况下只能基于旧版本升级。 
 -e 是否有额外运行的脚本 
 -p 定义脚本用到的一些可执行文件的路径。 
 -s 定义额外运行脚本的路径。 
 -x 定义额外运行的脚本可能用的键值对。 
 -v 执行过程中打印出执行的命令。 
 -h 命令帮助 
 -m 执行过程中生成脚本(updater-script)所需要的格式,目前有两种即amend和edify。对应上两种版本升级时会采用不同的解释器。缺省会同时生成两种格式的脚本。 

2.制作差分包

使用命令制作差分包

 ./build/tools/releasetools/ota_from_target_files -v -p out/host/linux-x86/ -i ota/v1.zip ota/v2.zip ota/update.zip

差分包原包:
out/target/product/project/obj/PACKAGING/target_files_intermediates/project-target_files-mp5V4129.zip
整包:
out/target/product/project/project-ota-mp5V4129.zip

3.跳过Recovery菜单选择界面,直接进入线刷模式

  • 源码:bootable/recovery/recovery.cpp
+int update_complete = 0;
 static Device::BuiltinAction PromptAndWait(Device* device, InstallResult status) 
   auto ui = device->GetUI();
   bool update_in_progress = (device->GetReason().value_or("") == "update_in_progress");
@@ -395,19 +396,24 @@ static Device::BuiltinAction PromptAndWait(Device* device, InstallResult status)
                   "  Your device may fail to boot if you reboot or power off now." ;
     
 
-    size_t chosen_item = ui->ShowMenu(
-        headers, device->GetMenuItems(), 0, false,
-        std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
-    // Handle Interrupt key
-    if (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::INTERRUPTED)) 
-      return Device::KEY_INTERRUPTED;
-    
-    // Device-specific code may take some action here. It may return one of the core actions
-    // handled in the switch statement below.
-    Device::BuiltinAction chosen_action =
-        (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::TIMED_OUT))
-            ? Device::REBOOT
-            : device->InvokeMenuItem(chosen_item);
+    Device::BuiltinAction chosen_action = Device::NO_ACTION;
+    if (update_complete > 0)
+        size_t chosen_item = ui->ShowMenu(
+            headers, device->GetMenuItems(), 0, false,
+            std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
+        // Handle Interrupt key
+        if (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::INTERRUPTED)) 
+          return Device::KEY_INTERRUPTED;
+        
+        // Device-specific code may take some action here. It may return one of the core actions
+        // handled in the switch statement below.
+        chosen_action =
+            (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::TIMED_OUT))
+                ? Device::REBOOT
+                : device->InvokeMenuItem(chosen_item);   
+     else 
+        // 默认选择线刷模式
+        chosen_action = Device::APPLY_ADB_SIDELOAD;
+          
 
     switch (chosen_action) 
       case Device::REBOOT_FROM_FASTBOOT:    // Can not happen
@@ -496,6 +502,7 @@ static Device::BuiltinAction PromptAndWait(Device* device, InstallResult status)
           ui->Print("Installation aborted.\\n");
           copy_logs(save_current_log);
         
+        update_complete = 1;
         break;
       

4.使用adb进行升级

设备先刷入v1版本软件
进入recovery模式

adb reboot recovery

稍等一会界面会提示

Now send the package you want to apply 
to the device with "adb sidelaod <filename>"...

输入命令开始升级

adb sideload Z:\\xxx\\xxx\\ota\\update.zip

update.zip是制作好的差分包

5.出现kDownloadStateInitializationError错误

结果并没有成功,界面显示

Now send the package you want to apply 
to the device with "adb sidelaod <filename>"...

Supported API: 3
Finding update package...
Verifying update package...
Update package verification took 0.2s (result 0).
Installing update...
Step 1/2
Error applaying update: 20 (ErrorCode:kDownloadStateInitializationError)
EError in /sideload/package.zip(status 1)

Install from ADB completed with status 1.
Installation aborted.

导出recovery.log

adb pull /tmp/recovery.log d:/log

关键log如下

[   12.789101] update_engine_sideload I 03-22 03:23:25   243   243 [INFO:delta_performer.cc(397)] Applying 432 operations to partition "system"
[   16.874701] update_engine_sideload I 03-22 03:23:29   243   243 [INFO:delta_performer.cc(209)] Completed 147/667 operations (22%), 2785280/2788529 bytes downloaded (99%), overall progress 60%
[   21.930529] update_engine_sideload I 03-22 03:23:34   243   243 [INFO:delta_performer.cc(209)] Completed 281/667 operations (42%), 2785280/2788529 bytes downloaded (99%), overall progress 70%
[   27.169636] update_engine_sideload I 03-22 03:23:39   243   243 [INFO:delta_performer.cc(209)] Completed 414/667 operations (62%), 2785280/2788529 bytes downloaded (99%), overall progress 80%
[   27.628061] I:current maximum temperature: 53400
[   30.098801] update_engine_sideload I 03-22 03:23:42   243   243 [INFO:delta_performer.cc(385)] Opening /dev/block/platform/soc/11230000.mmc/by-name/lk_b partition without O_DSYNC
[   30.106429] update_engine_sideload I 03-22 03:23:42   243   243 [INFO:delta_performer.cc(128)] Caching writes.
[   30.106723] update_engine_sideload I 03-22 03:23:42   243   243 [INFO:delta_performer.cc(397)] Applying 6 operations to partition "lk"
[   30.148475] avb_footer.c:41: ERROR: Footer magic is incorrect.
[   30.155000] update_engine_sideload E 03-22 03:23:42   243   243 [ERROR:fec_file_descriptor.cc(30)] No ECC data in the passed file
[   30.155053] update_engine_sideload E 03-22 03:23:42   243   243 [ERROR:delta_performer.cc(431)] Unable to open ECC source partition lk on slot A, file /dev/block/platform/soc/11230000.mmc/by-name/lk_a: Invalid argument (22)
[   30.155089] update_engine_sideload E 03-22 03:23:42   243   243 [ERROR:delta_performer.cc(1158)] The hash of the source data on disk for this operation doesn't match the expected value. This could mean that the delta update payload was targeted for another version, or that the source partition was modified after it was installed, for example, by mounting a filesystem.
[   30.155110] update_engine_sideload E 03-22 03:23:42   243   243 [ERROR:delta_performer.cc(1163)] Expected:   sha256|hex = D19BC4D6CE0BB9DA353AD26EFBD9D3A889EE24B926E0843E94E68F945C8BB1FD
[   30.155143] update_engine_sideload E 03-22 03:23:42   243   243 [ERROR:delta_performer.cc(1166)] Calculated: sha256|hex = 9DD7A21C4009F84D831B64A483684DD27AB9D200AF935D4C2F4C3904F664B87F
[   30.155163] update_engine_sideload E 03-22 03:23:42   243   243 [ERROR:delta_performer.cc(1177)] Operation source (offset:size) in blocks: 0:128,129:41
[   30.155529] update_engine_sideload E 03-22 03:23:42   243   243 [ERROR:delta_performer.cc(1498)] source_fd != nullptr failed.
[   30.155554] update_engine_sideload E 03-22 03:23:42   243   243 [ERROR:delta_performer.cc(297)] Failed to perform BROTLI_BSDIFF operation 463, which is the operation 1 in partition "lk"
[   30.155575] update_engine_sideload E 03-22 03:23:42   243   243 [ERROR:download_action.cc(336)] Error ErrorCode::kDownloadStateInitializationError (20) in DeltaPerformer's Write method when processing the received payload -- Terminating processing

从log上可以看到是应用lk分区是出错,Hash值不匹配

原因: make otapackage 会对.img重新打包 导致重新打包的.img和out目录下的.img Hash值不一致. 也就是线刷版本的.img和OTA包的.img不一致;整包升级会替换.img,而差分包升级则需要保证系统内部的.img和整包中.img一致才能升级成功(差分包中保存了通过sha256 Hash算法计算出整包.img的值,通过这个值来确定两个.img一致).

做了如下两种测试
①使用差分包原包中的.img文件
使用out/target/product/project/obj/PACKAGING/target_files_intermediates/project-target_files-mp5V4129下的lk.imgtee.img替换掉out/target/product/project/下的文件,刷机后再进行OTA差分升级成功
②解包payload.bin
payload.bin文件是由整包文件解压得来的,使用payload.bin解包后中的lk.imgtee.img替换掉out/target/product/project/下的文件,刷机后再进行OTA差分升级成功

注意:如果开启了verify模式,out目录下lk-verified.imgtee-verified.img这两个文件需要disable掉,下载的时候会优先选择verify文件

6.OTA升级失败错误码

ErrorCode::kSuccess (0) 升级成功
ErrorCode::kSuccess (1) 升级失败
ErrorCode::kFilesystemCopierError (4) 未知,暂时未使用的错误码
ErrorCode::kPostinstallRunnerError (5) 升级安装结束,设置启动分区失败
ErrorCode::kPayloadMismatchedType (6) 升级包的升级类型不匹配或升级包minor version不兼容
ErrorCode::kInstallDeviceOpenError (7) 无法启动升级。可能是原因:分区错误,设备支持升级的分区和升级包内的不匹配;设备处于disable-verity状态;
ErrorCode::kKernelDeviceOpenError (8) 未知,暂时未使用的错误码
ErrorCode::kDownloadTransferError (9) w,找不到升级包
ErrorCode::kPayloadHashMismatchError (10) FILE_HASH值不匹配
ErrorCode::kPayloadSizeMismatchError (11) 数据size不匹配
ErrorCode::kDownloadPayloadVerificationError (12) 签名验证失败
ErrorCode::kDownloadStateInitializationError (20) 升级包写入时失败  一般都是发生在差分包升级时,检测boot、system、vendor的hash值不匹配。
ErrorCode::kDownloadInvalidMetadataMagicString (21)  未找到正确bin文件,一般是offset不对导致
ErrorCode::kDownloadInvalidMetadataSize (32) METADATA_SIZE值不匹配
ErrorCode::kPayloadTimestampError (51) 升级包的date比机器当前版本早

Android 系统OTA升级
Android系统OTA差分升级失败kDownloadStateInitializationError
Android OTA差分包升级失败

adb remount之后,OTA 升级失败的问题

MTK平台,remount后ota升级失败


userdebug版本,remount升级失败

adb root
adb remount
然后push了一堆东西进去,ota升级的时候会报空间不够,我们先看mtk的debug log

 473   473 I update_engine: [1101/114216.247577:INFO:dynamic_partition_control_android.cc(197)] Loaded metadata from slot A in /dev/block/platform/bootdevice/by-name/super
 473   473 I update_engine: [1101/114216.247946:INFO:boot_control_android.cc(312)] Removing group main_b
 473   473 I update_engine: [1101/114216.248105:INFO:boot_control_android.cc(343)] Added group main_b with size 1844969472
 473   473 I /system/bin/update_engine: [liblp]Partition vendor_b will resize from 0 bytes to 327540736 bytes
 473   473 I update_engine: [1101/114216.248254:INFO:boot_control_android.cc(360)] Added partition vendor_b to group main_b with size 327540736
 473   473 I /system/bin/update_engine: [liblp]Partition product_b will resize from 0 bytes to 252170240 bytes
 473   473 I update_engine: [1101/114216.248382:INFO:boot_control_android.cc(360)] Added partition product_b to group main_b with size 252170240
 473   473 E /system/bin/update_engine: [liblp]Not enough free space to expand partition: system_b
 473   473 E update_engine: [1101/114216.248480:ERROR:boot_control_android.cc(356)] Cannot resize partition system_b to size 1154273280. Not enough space?
 473   473 E update_engine: [1101/114216.248544:ERROR:delta_performer.cc(998)] Unable to initialize partition metadata for slot B
 473   473 E update_engine: [1101/114216.248630:ERROR:download_action.cc(336)] Error ErrorCode::kInstallDeviceOpenError (7) in DeltaPerformer's Write method when processing the received payload -- Terminating processing
 473   473 I update_engine: [1101/114216.249175:INFO:multi_range_http_fetcher.cc(177)] Received transfer terminated.
 473   473 I update_engine: [1101/114216.249358:INFO:multi_range_http_fetcher.cc(129)] TransferEnded w/ code 200
 473   473 I update_engine: [1101/114216.249451:INFO:multi_range_http_fetcher.cc(131)] Terminating.
1236  1524 V FespxProcessor: onMultibfDataReceived: 8 index 0 size 4096 mPreUploadRollbackDataSize 131072
 473   473 I update_engine: [1101/114216.253259:INFO:action_processor.cc(116)] ActionProcessor: finished DownloadAction with code ErrorCode::kInstallDeviceOpenError
 473   473 I update_engine: [1101/114216.253452:INFO:action_processor.cc(121)] ActionProcessor: Aborting processing due to failure.
 473   473 I update_engine: [1101/114216.253521:INFO:update_attempter_android.cc(454)] Processing Done.
 473   473 I update_engine: [1101/114216.253568:INFO:dynamic_partition_control_android.cc(151)] Destroying [] from device mapper
3254  3272 D clifeOTA: onStatusUpdate  status: 0
 473   473 I update_engine: [1101/114216.254265:INFO:metrics_repo

原因分析:

看这句
ERROR:boot_control_android.cc(356)] Cannot resize partition system_b to size 1154273280. Not enough space?
意思是空间不够,查看储存,16G内存只占用了5G多,实际内存多,为什么内存不够, 主要是看对分区的内存,结合MTKAB分区这个链接里面的分区,partition_ab_dynamic.xml,或者partition_dynamic.xml 这两个文件可以看到对super分区和userdata分区的大小,如userdata分区6291456* 512 / 1024 /1024 /1024 =3 G,表示用户空间占3G,出错原因主要是super分区的大小导致的,一般情况下是16G以上的内存的话, AB分区各占1.5G左右,然后adb remount之后会产生一个overlay的scratch分区,这个分区实际上占用在super分区上的,具体占用多少内存还是看 product,vendor,system三个目录的大小,这样,如果super分区太小的话,在AB OTA升级的时候,就是导致动态分区不够,导致升级失败,因OTA升级时不会清除scratch分区的,我这里为什么会报错,是因为改了内存,从16G降到了8G,然后其他同事改分区的时候只减小修改了super分区大小为3G多,所以userdebug版本,remount之后,overlay占用了super分区,导致升级slot b分区的时候,动态分配分区内存就不够,所以升级失败。

<?xml version="1.0" encoding="utf-8"?>
<partition lba="31457280">

<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="6144" name="proinfo"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="30720" name="cam_vpu1_a"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="30720" name="cam_vpu2_a"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="30720" name="cam_vpu3_a"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="30720" name="cam_vpu1_b"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="30720" name="cam_vpu2_b"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="30720" name="cam_vpu3_b"/>
	
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="10240" name="nvram"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="20480" name="protect1"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="20480" name="protect2"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="98304" name="persist"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="16384" name="nvcfg"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="512" name="seccfg"/>
	
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="2048" name="lk_a"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="2048" name="lk_b"/>
	
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="65536" name="boot_a"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="65536" name="boot_b"/>
	
	<!-- <entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="65536" name="recovery"/> -->
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="1024" name="para"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="16384" name="logo"/>
	
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="16384" name="dtbo_a"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="16384" name="dtbo_b"/>
	
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="20480" name="expdb"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="2048" name="frp"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="10240" name="tee_a"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="10240" name="tee_b"/>
	
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="4096" name="kb"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="4096" name="dkb"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="65536" name="metadata"/>
	
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="11520" name="vbmeta_a"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="11520" name="vbmeta_b"/>
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="8192" name="nvdata" />
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="4096" name="vbmeta_system_a" />
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="4096" name="vbmeta_system_b" />
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="4096" name="vbmeta_vendor_a" />
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="4096" name="vbmeta_vendor_b" />
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="16769024" name="super"/>
	<!-- <entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="229376" name="cache"/>  -->
	<entry type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" size="6291456" name="userdata"/>
</partition>

我们对比前后lpdump分区的区别,adb remount之后,
看分区 Name: scratch

C:\\Users\\aaa>adb shell
xxxx:/ $ lpdump
Metadata version: 10.0
Metadata size: 844 bytes
Metadata max size: 65536 bytes
Metadata slot count: 3
Partition table:
------------------------
  Name: vendor_a
  Group: main_a
  Attributes: readonly
  Extents:
    0 .. 639727 linear super 2048
------------------------
  Name: vendor_b
  Group: main_b
  Attributes: readonly
  Extents:
------------------------
  Name: product_a
  Group: main_a
  Attributes: readonly
  Extents:
    0 .. 492511 linear super 643072
------------------------
  Name: product_b
  Group: main_b
  Attributes: readonly
  Extents:
------------------------
  Name: system_a
  Group: main_a
  Attributes: readonly
  Extents:
    0 .. 2254431 linear super 1136640
------------------------
  Name: system_b
  Group: main_b
  Attributes: readonly
  Extents:
------------------------
  Name: scratch
  Group: default
  Attributes: none
  Extents:
    0 .. 1295 linear super 641776
    1296 .. 2351 linear super 1135584
    2352 .. 1910119 linear super 3391072
------------------------
Block device table:
------------------------
  Partition name: super
  First sector: 2048
  Size: 3690987520 bytes
  Flags: none
------------------------
Group table:
------------------------
  Name: default
  Maximum size: 0 bytes
  Flags: none
------------------------
  Name: main_a
  Maximum size: 1844969472 bytes
  Flags: none
------------------------
  Name: main_b
  Maximum size: 1844969472 bytes
  Flags: none
------------------------

正常设备lpdump

C:\\Users\\xxxx>adb shell
xxxx:/ $ lpdump
Metadata version: 10.0
Metadata size: 720 bytes
Metadata max size: 65536 bytes
Metadata slot count: 3
Partition table:
------------------------
  Name: vendor_a
  Group: main_a
  Attributes: readonly
  Extents:
    0 .. 639727 linear super 2048
------------------------
  Name: vendor_b
  Group: main_b
  Attributes: readonly
  Extents:
------------------------
  Name: product_a
  Group: main_a
  Attributes: readonly
  Extents:
    0 .. 492511 linear super 643072
------------------------
  Name: product_b
  Group: main_b
  Attributes: readonly
  Extents:
------------------------
  Name: system_a
  Group: main_a
  Attributes: readonly
  Extents:
    0 .. 2254431 linear super 1136640
------------------------
  Name: system_b
  Group: main_b
  Attributes: readonly
  Extents:
------------------------
Block device table:
------------------------
  Partition name: super
  First sector: 2048
  Size: 3690987520 bytes
  Flags: none
------------------------
Group table:
------------------------
  Name: default
  Maximum size: 0 bytes
  Flags: none
------------------------
  Name: main_a
  Maximum size: 1844969472 bytes
  Flags: none
------------------------
  Name: main_b
  Maximum size: 1844969472 bytes
  Flags: none
------------------------

解决方案:

1.暂时解决方案,清楚了为什么会失败,那么只需要关掉overlay就行
adb root
adb enable-verity
adb reboot
搞定

2.上面只是短暂解决问题,根本上解决,还是要修改super分区大小
怎么算,比如userdata分区6291456* 512 / 1024 /1024 /1024 =3 G
一个8G的话,一般系统占用时1.5G左右,要想remount没有问题的话,至少需要
1.5 * 2 + overlay分区的占用, 这里的话,我写一个4G, 8388608的,在测试,ok,
注意, 所有加起来的大小不能超过 这个,不然编译不过

以上是关于Android11.0 OTA差分包升级失败kDownloadStateInitializationError的主要内容,如果未能解决你的问题,请参考以下文章

解决高通 Android 12/13 ota升级失败问题

手把手实现andriod应用增量升级

Android差分升级原理和实现方式

转Android开发之增量更新

adb remount之后,OTA 升级失败的问题

Android OTA升级