整包:是可以直接用于OTA升级使用,相当于整个替换机器image。优点是操作简单,不容易出问题。缺点是内存很大。
基础包:是用于制作差分包。里面包含所有支持升级的image文件。将新旧两个基础包,使用系统自带脚本进行对比差分操作后,就会按照新旧的差异点生成一个差分包。
差分包:是只有包含差点点信息和差异patch的。所以使用差分包升级,一定要保证机器里面当前的image和制作差分的基础包里面的image完全一致。否则肯定升级失败。
1.1、编译一个完整刷机包
1.2、制作OTA包
在android目录下执行 make otapackage –j8 编译OTA包。以450平台为例,编译后会在
out\target\product\**\ 目录下生成一个整包: msm8953_64-ota-*.zip
out\target\product\**\obj\PACKAGING\target_files_intermediates目录下生成一个基础包: msm8953_64-*.zip
差分包制作执行源码脚本:Android R 需要增加 -p 参数指向依赖的二进制文件
./build/tools/releasetools/ota_from_target_files (-p out/host/linux-x86) -v -i old.zip new.zip update.zip
Recovery升级是原生默认的升级方式,后面某些高端平台可能会默认废弃这种方式。升级基于recovery分区进行,对image进行升级操作。这种升级方式,优点是节省ROM,缺点是如果发生意外导致系统image损坏,机器就可能变砖了。
执行如下 adb 指令进行升级操作
adb root
adb remount
adb push update.zip /data/update.zip
adb shell
uncrypt /data/update.zip /cache/recovery/block.map
echo "--update_package=@/cache/recovery/block.map" > /cache/recovery/command
adb reboot recovery
注:7.0之前系统没有uncrypt,将升级包push到/cache/update.zip,再执行如下指令
adb root
adb remount
adb push update.zip / cache /update.zip
adb shell
echo " --update_package=/cache/update.zip " > /cache/recovery/command
adb reboot recovery
方法一:使用系统自带API相关接口文件叫 android.os.RecoverySystem,调用其 installPackage 等方法即可。注意权限需要是系统APP才可以。
方法二:adb reboot recovery 进入到 recovery 界面,有如下两项
Apply update from ADB
Apply update from SD Card
这两种都可以升级,选择后根据界面提示操作即可。
备注:可能有些平台没有这个界面功能。
AB升级模式应该是后续主要升级模式。原理就是在ROM中分了两个区域,各自有一套image。优点是更安全,即使是一套分区出问题了,仍然有一套可以使用,机器不会变砖。缺点就是多一套分区导致ROM占用更多。
adb root
adb remount
adb push update.zip data/ota_package/update.zip
adb shell
update_engine_client --update --follow --payload=file:///data/ota_package/update.zip --offset=7919 --size=724346 --headers="FILE_HASH=1RilNlJjIRfwwd8t86YucEhJV67msLzETHprS+HcWyg=
FILE_SIZE=724346
METADATA_HASH=vQsISDOuPUCkczn6FizKVHV8mkF8YqNYnNi21l6Du9o=
METADATA_SIZE=440778
"
update_engine_client后面的参数根据OTA包生成。表示OTA包的参数。新建ota.py,将下面代码复制过去,再执行python脚本 python ota.py update.zip 即会生成。
#!/usr/bin/env python
import sys
import zipfile
def main():
if len(sys.argv) != 2:
sys.stderr.write('Use: %s \n' % sys.arv[0])
return 1
otazip = zipfile.ZipFile(sys.argv[1], 'r')
payload_info = otazip.getinfo('payload.bin')
payload_offset = payload_info.header_offset + len(payload_info.FileHeader())
payload_size = payload_info.file_size
payload_location = '/data/ota_package/update.zip'
headers = otazip.read('payload_properties.txt')
print (
'update_engine_client --update --follow --payload=file://{payload_location}'
' --offset={payload_offset} --size={payload_size}'
' --headers="{headers}"').format(**locals())
return 0
if __name__ == '__main__':
sys.exit(main())
执行update_engine_client指令后,等待升级完成,窗口有如下相关提示,表示升级成功。
[INFO:update_engine_client_android.cc(90)] onStatusUpdate(UPDATE_STATUS_UPDATED_NEED_REBOOT (6), 0)
[INFO:update_engine_client_android.cc(98)] onPayloadApplicationComplete(ErrorCode::kSuccess (0))
需要使用系统相关接口,android.os.UpdateEngine android.os.UpdateEngineCallback。
UpdateEngine.applyPayload 升级接口
UpdateEngineCallback是升级监听,如下:
class MyUpdateEngineCallback extends UpdateEngineCallback {
@Override
public void onStatusUpdate(int status, float percent) {
Log.i(TAG, "percent:" + percent);
if (percent > 0)
mInfoTextView.setText("升级进度:" + percent);
}
@Override
public void onPayloadApplicationComplete(int errorCode) {
Log.i(TAG, "errorCode:" + errorCode);
if (errorCode == 0) {
handler.sendEmptyMessage(UPDATE_SUCCESS);
} else {
Message msg = new Message();
msg.what = UPDATE_ERROR;
Bundle bundle = new Bundle();
bundle.putInt("errorCode", errorCode);
msg.setData(bundle);
handler.sendMessage(msg);
}
if (mUpdateEngine != null) {
mUpdateEngine.unbind();
}
}
}
通过查看 ro.boot.slot_suffix 属性值的方式,这个属性值显示当前使用分区名
通过进入bootloader 模式,指定启动槽值来选择下次启动的分区,按照如下指令即可
adb reboot bootloader
fastboot --set-active=a
fastboot reboot
升级结束时,可以看到有个错误码,常见错误码如下,按照错误码去查找可能原因
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比机器当前版本早
system/update_engine/update_engine_client_android.cc