Android设备集成Android SDK、鉴权和还原算法,并完成相应开发后,您可以使用差分工具生成差分升级包(以下简称差分包),上传到物联网平台控制台用于OTA升级。升级时,物联网平台推送差分包至设备,设备对差分包进行差分还原,形成完整的升级包。下面介绍差分升级流程和相应的设备开发,以及差分包生成方法。

差分升级流程

流程

差分升级流程如上图所示。

  1. 设备端上报OTA模块当前版本。
  2. 用户通过控制台添加差分包。控制台对设备发送OTA升级请求。

    通过差分工具生成差分包的方法,请参见生成差分包

  3. OTA服务端下发差分包的URL给设备端。
  4. 设备端通过HTTPS协议,根据差分包URL下载差分包,对差分包进行鉴权、差分还原。
    1. 鉴权:进行差分还原前,调用Abup_verifyActivation_main函数进行鉴权。鉴权通过,即可进入差分还原流程,读写差分包文件;若鉴权失败,则终止升级流程。
    2. 差分还原:调用Abup_BSDiffPatch函数进行差分还原,将差分包还原为完整的升级包文件。
  5. 设备端上报升级进度信息。控制台显示升级进度。
  6. 设备端完成OTA升级后,上报最新版本。控制台显示升级成功。

请您下载鉴权和差分还原算法集成到设备Android SDK,完成相应设备开发,实现上述差分升级流程。差分升级程序,请参见OTA升级程序代码。数据流转Topic和数据格式,请参见设备端OTA升级

我们同时提供集成了Android SDK和差分升级程序的Demo App,您也可以通过Demo App实现差分升级流程。

生成差分包

说明 差分工具支持生成Android 7.0、7.1的差分包。

差分工具运行环境:

名称 版本
Ubuntu 64位中文版Ubuntu系统。支持14.04、16.04、18.04,推荐使用16.04。
JDK 1.8及以上。
Python 2.7。
libc++.so 1.0。

操作步骤:

  1. 下载差分工具
  2. 安装差分工具。
    1. 切换至根目录下,执行以下命令安装delta文件。
      sudo dpkg -i ab-delta-xxx.deb
    2. bsdiff、imgdiff和migration需要运行权限,切换至差分工具的bin目录下,执行以下命令:
      chmod +x bsdiff imgdiff
      chmod -R +x migration
    3. 执行以下命令安装库文件。
      sudo apt-get install liblzo2-2
      sudo apt-get install libstdc++6 
      sudo apt-get install lib32stdc++6
    4. 执行以下命令进行差分工具安装。
      sudo apt-get install p7zip
  3. 使用差分工具生成差分包。
    1. 执行以下命令运行差分工具。
      java -jar deltaToolClient4.1.0.jar
      进入如下初始化页面:初始化页面
    2. 准备移植包。

      移植包是OTA功能涉及到平台文件的修改。

      单击初始化页面的生成移植包。如下图所示,选择设备对应的芯片平台以及安卓版本,单击打开移植包文件夹,找到对应芯片平台的移植包文件。生成移植包
    3. 移植包合入工程。
      将上一步生成的移植包合入到安卓工程,详细操作请参考移植包中的readme.txt文件。
    4. 编译版本。
      分别编译OTA升级前后的源版本、目标版本,生成OTA包,用于制作差分包。
      说明 源版本与目标版本的OTA包格式必须一致。支持ZIP、RAR格式,推荐使用ZIP格式。
    5. 生成差分包。
      单击初始化页面的制作差分包。如下图所示,选择上一步编译源版本、目标版本生成的OTA包,单击下一步选择OTA包

      差分工具对源版本、目标版本进行解析。界面提示解析完成后,单击下一步

      差分工具生成差分包。界面提示生成升级包成功后,单击打开差分文件夹,获取差分包文件update.zip

      说明 生成差分包的过程较长,请耐心等待,请勿关闭程序,以免发生异常。

生成差分包常见问题

  • 问:为什么出现Can not find/usr/错误?

    答:没有安装delta文件。执行sudo dpkg -i ab-delta-xxx.deb命令安装delta文件。

  • 问:为什么执行sudo dpkg -i ab-delta-xxx.deb时出错?

    答:可能是Ubuntu版本不符合要求,需要64位Ubuntu系统。

  • 问:为什么差分失败,提示diff超时?

    答:建议重试。多次重试不成功,可能是电脑配置较低所致。

  • 问:为什么无法创建文件夹?

    答:请查看用户是否有权限在此目录创建文件夹。

  • 问:生成差分包过程报错,如何查看日志?

    答:工具目录下,Logs文件夹内有相关日志。

  • 问:日志显示如下错误,如何处理?日志

    答:磁盘空间不足,请预留2GB以上磁盘空间。

OTA升级程序代码

差分升级流程中,为了进入第4步的鉴权和差分还原,您需要在非差分升级程序代码的基础上做修改。下面仅展示修改的部分,非差分升级完整程序代码和详细说明,请参见设备OTA开发

依赖改为:

//阿里云Android SDK
implementation('com.aliyun.alink.linksdk:iot-linkkit:1.7.1.5')
//差分JAR包
compile('com.aliyun.alink.linksdk:abup:1.0.0')

差分升级需要的数据,通过onOtaProgress函数回调getExtData方法获得,程序代码改为:

mOta.tryStartOta(mConfig, new OtaListener() {
    public boolean onOtaProgress(int step, IOta.OtaResult otaResult) {
        int code = otaResult.getErrorCode();
        Object data = otaResult.getData();
        // 如果是差分升级,返回extra,示例{"authKey":"****","authMethod":"ABUP"}。
        Map extra = otaResult.getExtData();
        if (code != IOta.NO_ERROR) {
            Log.e(TAG, "onOtaProgress error:" + code);
            // 为用户展示提示信息。
            return false;
        }

        switch (step) {
            case IOta.STEP_REPORT_VERSION:
                // 上报版本。
                break;
            case IOta.STEP_SUBSCRIBE:
                // 订阅回调。
                break;
            case IOta.STEP_RCVD_OTA:
                // 有新的OTA升级包,返回true,表示继续升级。
                otaInfo = (OtaInfo) data;
                // 为用户展示升级包信息。
                return true;
                break;
            case IOta.STEP_DOWNLOAD:
                // 下载升级包中。
                int progress = (int) data;
                // 若需要,可为用户展示进度值。
                break;
        }

        return true;
    }
});

Abup_verifyActivation_main函数

Abup_verifyActivation_main函数用于在读写升级文件前进行鉴权。

原型:

Bool Abup_verifyActivation_main()

返回值:

  • 0:鉴权通过。
  • 1:鉴权失败。

License要求:

在设备执行升级命令前,需要将License文件放在设备的/cache/recovery目录下,且文件名为authentication_file,无扩展名。

License文件内容为mid&&key,其中:
  • mid是设备所属产品的ProductKey和设备的DeviceName连接在一起。ProductKey、DeviceName可在设备详情页查看。例如:ProductKey为a1BwAGV****,DeviceName为light,则mid为a1BwAGV****light
  • key是从下发升级指令的Topic中获取的authKey。

示例代码:

bootable/recovery/updater/blockimg.cpp的BlockImageUpdate()函数中加入以下代码:

if(Abup_verifyActivation_main()){
   fprintf(stderr,"Abup_verifyActivation_main is FALSE\n");
   return StringValue(strdup(""));
}

Abup_BSDiffPatch函数

Abup_BSDiffPatch函数是差分还原算法的实现入口。

原型:

int Abup_BSDiffPatch(const unsigned char* old_data,
ssize_t oldsize,
char* patch_data,
ssize_t patch_offset,
size_t *new_data_size,
char **new_data_buf)

参数说明:

参数 输入/输出 数据类型 说明
old_data 输入 const unsigned char* 需要升级的当前数据起始地址指针。
oldsize 输入 ssize_t 需要升级的当前数据的大小,单位byte。
patch_data 输入 char* 差分包中的patch数据地址指针。
patch_offset 输入 ssize_t 差分包中的patch数据的偏移量。
*new_data_size 输出 size_t patch还原后的新数据大小,单位byte。
**new_data_buf 输出 char patch还原后的新数据存储地址。
注意 new_data_buf使用完毕后,必须进行释放,以免造成内存泄露。

返回值:

0

示例代码:

int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t oldsize,
                        const Value* patch, ssize_t patch_offset,
                        std::vector<unsigned char>* new_data) {
    // Patch数据格式:
    // Header为"ABUPDF41"+total_memory(1 byte)+patch_total_size(4 bytes)
    char *new_databuf = NULL;
    size_t new_dataSize = 0;
    //调用Abup_BSDiffPatch函数。
    if(Abup_BSDiffPatch(old_data, oldsize,
                        patch->data , patch_offset, 
                        &new_dataSize ,&new_databuf) != 0) {
       return -1;
    }
    if((new_databuf == NULL)||(new_dataSize == 0)) {
       printf("ApplyBSDiffPatchMem :new_databuf is NULL or new_dataSize==0\n");
       return -1;
    }
    printf("ApplyBSDiffPatchMem :new_dataSize ==%ld \n",new_dataSize);
    new_data->resize(new_dataSize);
    memcpy(new_data->data(), new_databuf, new_dataSize);
    free(new_databuf);
    return 0;
}

注意事项:

在使用差分工具生成差分包时,我们对差分包中每个patch数据打上ABUPDF41标签(一般情况下,差分包patch数据的标签为 BSDIFF40)。所以当使用差分还原算法时,请将差分还原算法外层判断BSDIFF40标签的代码,修改为判断ABUPDF41。如不修改,设备可能无法正常使用差分还原算法。

修改示例:

修改的文件:以AOSP Android-7.1.2_r18为例,修改bootable/recovery/applypatch/applypatch.cpp

修改前:if (header_bytes_read >= 8 && memcmp(header, "BSDIFF40", 8) == 0) { use_bsdiff = true;

修改为:if (header_bytes_read >= 8 && memcmp(header, "ABUPDF41", 8) == 0) { use_bsdiff = true;

Demo App

您可以使用集成了Android SDK和差分升级程序的Demo App实现差分升级。

操作步骤:

  1. 下载IoTDeviceSDKDemo,并解压缩。
  2. 配置设备信息。
    app/src/main/res/raw/deviceInfo文件中,写入设备证书:ProductKey、DeviceName、ProductSecret。
  3. 设备安装App,并初始化。
    首次进入App时会自动进行初始化。如果初始化失败,则可以在App首页DemoActivity进行手动初始化。
    说明 需要给App添加系统签名,以便作为系统应用进入recovery模式进行OTA升级。
  4. OTA升级。
    在App的OTA示例页面,单击开始OTA,App自动上报设备固件版本,并准备接受物联网平台的OTA指令。

    收到OTA指令后,App自动开始下载升级文件(完整升级包或差分包),显示下载进度。下载完成后自动开始升级,同时上报升级进度。

    升级完成后,App自动上报最新版本。
    说明 默认通过获取设备build.prop文件中的ro.fota.version字段值作为当前版本,可根据需要修改app/src/main/java/com/aliyun/alink/devicesdk/utils.java文件中的getVersion方法,获取其他字段作为当前版本。