Android 系统OTA升级

一、升级包制作流程

整包:是可以直接用于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升级是原生默认的升级方式,后面某些高端平台可能会默认废弃这种方式。升级基于recovery分区进行,对image进行升级操作。这种升级方式,优点是节省ROM,缺点是如果发生意外导致系统image损坏,机器就可能变砖了。

debug模式下调试OTA方法

执行如下 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

user版本需要可以使用系统API接口

方法一:使用系统自带API相关接口文件叫 android.os.RecoverySystem,调用其 installPackage 等方法即可。注意权限需要是系统APP才可以。

方法二:adb reboot recovery 进入到 recovery 界面,有如下两项

Apply update from ADB

Apply update from SD Card

这两种都可以升级,选择后根据界面提示操作即可。

备注:可能有些平台没有这个界面功能。


三、A/B分区模式升级

AB升级模式应该是后续主要升级模式。原理就是在ROM中分了两个区域,各自有一套image。优点是更安全,即使是一套分区出问题了,仍然有一套可以使用,机器不会变砖。缺点就是多一套分区导致ROM占用更多。

debug模式下调试

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))

user版本调试

需要使用系统相关接口,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();
            }
        }
    }

常见调试问题

a、如何确认AB升级当前分区

通过查看 ro.boot.slot_suffix 属性值的方式,这个属性值显示当前使用分区名

b、如何手动切换分区

通过进入bootloader 模式,指定启动槽值来选择下次启动的分区,按照如下指令即可

adb reboot bootloader

fastboot --set-active=a

fastboot reboot

c、如何判断失败原因

升级结束时,可以看到有个错误码,常见错误码如下,按照错误码去查找可能原因

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

你可能感兴趣的:(Android,android,sqlite)