Android9.0系统OTA升级update_engine

Android旧式的系统升级是在Recover模式下将U盘里面的update.zip升级包进行安装,这种方式不是特别的安全,如果升级过程中出现掉电,或者其他升级错误,容易造成机器变成砖,只能通过烧录才能修复。现在已使用全新的一套升级系统update_engine,这套系统的加入使原有的Recover变得多余,但是为了向下兼容所以还保留了Recover模块。update_engine升级思路是A/B升级模式,意思就是机器上有两套可引导系统,如果目前运行的是A系统则通过A引导升级B系统,如果是B系统则引导升级A系统。这样能保证手机不会变成砖,就算升级失败,那也还是原来的系统。全程后台运行,不影响用户使用。要想深入学习需要做大量功课,以下一个成功的demo。

模块路径:system/update_engine

测试程序:system/update_engine/update_engine_client_android.cc

测试模块是否打通:

  1. 制作升级包make otapackage
  2. 解压升级包out\target\product\product\update.zip
  3. 提取payload.bin、payload_properties.txt放置到指定下载路径或者U盘
  4. FILE_HASH、FILE_SIZE、METADATA_HASH这些参数在payload_properties.txt文件中
  5. --payload=可以是HTTP形式的URL,直接进行OTA
  6. 特别要注意--headers="最好在第一行,格式解析有换行的要求,不然参数传不下去

测试指令:

update_engine_client --payload=file:///storage/udisk/payload.bin --update --headers="
FILE_HASH=wpG0gLjbUg3uTQ4LTnXjPfH3rvjxCPAEHzCspps28Sg=
FILE_SIZE=589122832
METADATA_HASH=EAlcdErle8BiZLOMZUkWAcwVYdmZc6StLfPMQE0OwE4=
METADATA_SIZE=54970"

解析程序通过\n来进行切割,然后调用service_->applyPayload进行升级。

  if (FLAGS_update) {
    std::vector headers = base::SplitString(
        FLAGS_headers, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
    std::vector and_headers;
    for (const auto& header : headers) {
      and_headers.push_back(android::String16{header.data(), header.size()});
    }
    Status status = service_->applyPayload(
        android::String16{FLAGS_payload.data(), FLAGS_payload.size()},
        FLAGS_offset,
        FLAGS_size,
        and_headers);
    if (!status.isOk())
      return ExitWhenIdle(status);
  }

如果使用测试指令能成功升级,则可以直接用java接口进行升级工作。

package com.test.update.manager;

import java.net.MalformedURLException;
import java.net.URI;
import java.text.DecimalFormat;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import android.os.UpdateEngine;
import android.os.UpdateEngineCallback;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.net.Uri;
import android.util.Log;

public class SystemUpdateManager {

    public static final String ROOTDIR = "/storage/udisk/UpdatePack";

    public static final String PATH_PAYLOAD_BIN = ROOTDIR + "/OS/payload.bin";
    public static final String PATH_PAYLOAD_PROPERTIES = ROOTDIR + "/OS/payload_properties.txt";

    UpdateEngine mUpdateEngine;

    public SystemUpdateManager(Context context) throws MalformedURLException {
        mUpdateEngine = new UpdateEngine();
    }

    UpdateEngineCallback mUpdateEngineCallback = new UpdateEngineCallback {

        @Override
        public void onStatusUpdate(int status, float percent) {
            if (status == UpdateEngine.UpdateStatusConstants.DOWNLOADING) {// 回调状态,升级进度
                DecimalFormat df = new DecimalFormat("#");
                String progress = df.format(percent * 100);
                Log.d(TAG, "update progress: " + progress);
                if (this.mListener != null) {
                    this.mListener.onStateOrProgress(UpdateChangeListener.MESSAGE_UPDATE_PROGRESS,
                            0, progress);
                }
            }
        }

        @Override
        public void onPayloadApplicationComplete(int errorCode) {
            if (errorCode == UpdateEngine.ErrorCodeConstants.SUCCESS) {// 回调状态
                Log.d(TAG, "UPDATE SUCCESS!");
                if (this.mListener != null) {
                    this.mListener.onStateOrProgress(UpdateChangeListener.MESSAGE_WAIT_REBOOT, 0,
                            null);
                }
            }
        }

    };

    public void startUpdateSystem() {
        Uri uri = Uri.fromFile(new File(PATH_PAYLOAD_BIN));
        mUpdateEngine.bind(mUpdateEngineCallback);// 绑定callback
        mUpdateEngine.applyPayload(uri.toString(), 0l, 0l, getPayloadProperties());// 进行升级
    }

    // 读取payload_properties.txt
    public static String[] getPayloadProperties() {
        try {
            File file = new File(PATH_PAYLOAD_PROPERTIES);
            InputStreamReader is = new InputStreamReader(new FileInputStream(file));
            BufferedReader br = new BufferedReader(is);
            List lines = new ArrayList();
            String line = null;
            while ((line = br.readLine()) != null) {
                Log.d(TAG, "getPayloadProperties line: " + line);
                lines.add(line);
            }
            br.close();
            is.close();
            return lines.toArray(new String[lines.size()]);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

参考博客:https://blog.csdn.net/guyongqiangx/article/details/77650362

你可能感兴趣的:(Android,Framework,C++)