三、A/B 升级update_engine分析-客户端

本编将从两个方面分析客户端,原生测试模块update_engine_client和framwork层接口

一、update_engine_client

    Android原生编译出了测试模块update_engine_client,在system/bin/下,我个人理解是与framekwork 层binder机制连接update_engine服务端是类似的,不过该模块增加了命令行测试的部分。

   首先我们先根据android.mk看下大概依赖和文件,这就是我们先从android.mk开始的好处,大概知道了那些模块,需要看具体的再查看这个模块具体需要的内容

 1LOCAL_C_INCLUDES += \
 2    external/cros/system_api/dbus
 3LOCAL_SHARED_LIBRARIES += \  共享库依赖
 4    libbinder \
 5    libbinderwrapper \
 6    libbrillo-binder \
 7    libutils
 8LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/binder_bindings   aid文件
 9LOCAL_SRC_FILES := \  具体文件
10    binder_bindings/android/os/IUpdateEngine.aidl \
11    binder_bindings/android/os/IUpdateEngineCallback.aidl \
12    common/error_code_utils.cc \
13    update_engine_client_android.cc \
14    update_status_utils.cc

分析可执行程序先从main方法入手

1update_engine_client_android.cc
2
3int main(int argc, char** argv) {
4  //创建UpdateEngineClientAndroid 的对象client,并传入接收的参数
5  chromeos_update_engine::internal::UpdateEngineClientAndroid client(
6      argc, argv);
7  //返回client的run方法
8  return client.Run();
9}

UpdateEngineClientAndroid类的初始化

 1//UpdateEngineClientAndroid 继承了brillo 的Daemon类
 2class UpdateEngineClientAndroid : public brillo::Daemon {
 3 public:
 4  //根据main传入的argc argv变为私有的成员变量argc_ argv_
 5  UpdateEngineClientAndroid(int argc, char** argv) : argc_(argc), argv_(argv) {
 6  }
 7  //定义退出方法传入不同的参数
 8  int ExitWhenIdle(const Status& status);
 9  int ExitWhenIdle(int return_code);
10
11 private:
12  class UECallback : public android::os::BnUpdateEngineCallback {
13   public:
14    //C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的,
15    //而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,
16    //类构造函数默认情况下即声明为implicit(隐式).
17    explicit UECallback(UpdateEngineClientAndroid* client) : client_(client) {}
18
19    // android::os::BnUpdateEngineCallback overrides.
20    //重写callback的两个方法,监听升级状态和是否升级成功
21    Status onStatusUpdate(int status_code, float progress) override;
22    Status onPayloadApplicationComplete(int error_code) override;
23   
24   //客户端指针
25   private:
26    UpdateEngineClientAndroid* client_;
27  };
28  //重写父类的init方法
29  int OnInit() override;
30
31  // Called whenever the UpdateEngine daemon dies.
32  // 每当UpdateEngine守护程序终止时调用。
33  void UpdateEngineServiceDied();
34
35  // Copy of argc and argv passed to main().
36  // 拷贝从main方法传入的参数,也就是UpdateEngineClientAndroid的成员变量
37  int argc_;
38  char** argv_;
39  
40  //IUpdateEngine 指针service_
41  android::sp<android::os::IUpdateEngine> service_;
42  //BnUpdateEngineCallback 指针callback_
43  android::sp<android::os::BnUpdateEngineCallback> callback_;
44
45  brillo::BinderWatcher binder_watcher_;
46};

client.Run()方法

因为update_engine_client_android.cc中没有定义该方法,执行父类Daemon的run方法

 1external/libbrillo/brillo/daemons/daemon.cc
 2int Daemon::Run() {
 3  //执行onint方法,获得返回值exit_code
 4  int exit_code = OnInit();
 5  if (exit_code != EX_OK)
 6    return exit_code;
 7  //开启消息处理循环
 8  message_loop_.Run();
 9  //空方法,不用管
10  OnShutdown(&exit_code_);
11
12  // base::RunLoop::QuitClosure() causes the message loop to quit
13  // immediately, even if pending tasks are still queued.
14  // Run a secondary loop to make sure all those are processed.
15  // This becomes important when working with D-Bus since dbus::Bus does
16  // a bunch of clean-up tasks asynchronously when shutting down.
17  //base :: RunLoop :: QuitClosure()导致消息循环退出 即使待处理的任务仍在排队,也要立即运行。
18  //运行辅助循环以确保所有这些任务都得到处理。这在使用D-Bus时非常重要,
19  //因为dbus :: Bus在关闭时会异步执行大量清理任务。
20  //等待消息退出
21  while (message_loop_.RunOnce(false /* may_block */)) {}
22  //返回onint结果exit_code
23  return exit_code_;
24}

父类Daemon::OnInit()方法

 1external/libbrillo/brillo/daemons/daemon.cc
 2
 3int Daemon::OnInit() {
 4  async_signal_handler_.Init();
 5  for (int signal : {SIGTERM, SIGINT}) {
 6    //RegisterHandler注册信号SIGINT
 7    async_signal_handler_.RegisterHandler(
 8        signal, base::Bind(&Daemon::Shutdown, base::Unretained(this)));
 9  }
10  //RegisterHandler注册信号SIGHUP
11  async_signal_handler_.RegisterHandler(
12      SIGHUP, base::Bind(&Daemon::Restart, base::Unretained(this)));
13  //返回EX_OK;
14  return EX_OK;
15}

 

Daemon的子类UpdateEngineClientAndroid重写了Oninit方法,先调用子类的方法

 

  1update_engine_client_android.cc
  2
  3int UpdateEngineClientAndroid::OnInit() {
  4  //调用父类Daemon::OnInit()方法获得返回值
  5  int ret = Daemon::OnInit();
  6  if (ret != EX_OK)
  7    return ret;
  8  //以下这些是跟命令行参数有关的
  9  //定义update参数  “如果没有正在进行的更新,则开始新的更新。”
 10  DEFINE_bool(update, false, "Start a new update, if no update in progress.");
 11  //定义payload参数  升级使用的payload地址
 12  DEFINE_string(payload,
 13                "http://127.0.0.1:8080/payload",
 14                "The URI to the update payload to use.");
 15  //定义offset参数,调用服务端applyPayload包含该参数
 16  DEFINE_int64(offset, 0,
 17               "The offset in the payload where the CrAU update starts. "
 18               "Used when --update is passed.");
 19  //定义size参数,调用服务端applyPayload包含该参数
 20  DEFINE_int64(size, 0,
 21               "The size of the CrAU part of the payload. If 0 is passed, it "
 22               "will be autodetected. Used when --update is passed.");
 23  //定义headers参数,调用服务端applyPayload包含该参数
 24  DEFINE_string(headers,
 25                "",
 26                "A list of key-value pairs, one element of the list per line. "
 27                "Used when --update is passed.");
 28  //定义suspend参数 “暂停正在进行的更新并退出。”
 29  DEFINE_bool(suspend, false, "Suspend an ongoing update and exit.");
 30  //定义resume参数  恢复暂停的更新。
 31  DEFINE_bool(resume, false, "Resume a suspended update.");
 32  //定义cancel参数  取消正在进行的更新并退出。
 33  DEFINE_bool(cancel, false, "Cancel the ongoing update and exit.");
 34  //定义reset_status参数  重置已应用的更新并退出
 35  DEFINE_bool(reset_status, false, "Reset an already applied update and exit.");
 36  //定义follow参数  
 37  //“跟随状态更新将更改,直到达到最终状态为止。” “如果更新成功,则退出状态为0,否则为1。
 38  DEFINE_bool(follow,
 39              false,
 40              "Follow status update changes until a final state is reached. "
 41              "Exit status is 0 if the update succeeded, and 1 otherwise.");
 42
 43  // Boilerplate init commands.解析命令行参数
 44  base::CommandLine::Init(argc_, argv_);
 45  //解析argc_,argv_的参数,首行打印"Android Update Engine Client"
 46  brillo::FlagHelper::Init(argc_, argv_, "Android Update Engine Client");
 47  //如果没有参数输入,直接打印Nothing to do. Run with --help for help.
 48  if (argc_ == 1) {
 49    LOG(ERROR) << "Nothing to do. Run with --help for help.";
 50    return 1;
 51  }
 52
 53  // Ensure there are no positional arguments.确保没有位置参数。
 54  const std::vector<std::string> positional_args =
 55      base::CommandLine::ForCurrentProcess()->GetArgs();
 56  if (!positional_args.empty()) {
 57    LOG(ERROR) << "Found a positional argument '" << positional_args.front()
 58               << "'. If you want to pass a value to a flag, pass it as "
 59                  "--flag=value.";
 60    return 1;
 61  }
 62
 63  bool keep_running = false;
 64  //初始化log
 65  brillo::InitLog(brillo::kLogToStderr);
 66
 67  // Initialize a binder watcher early in the process before any interaction
 68  // with the binder driver.
 69  //binder_watcher初始化  在进行任何交互之前,在流程的早期初始化绑定监视程序
 70  binder_watcher_.Init();
 71  //获取服务端android.os.UpdateEngineService的服务,存储在service_,使用service_
 72  //调用服务端相应的方法
 73  android::status_t status = android::getService(
 74      android::String16("android.os.UpdateEngineService"), &service_);
 75  //如果获取服务失败,打印错误Failed to get IUpdateEngine binder from service manager
 76  if (status != android::OK) {
 77    LOG(ERROR) << "Failed to get IUpdateEngine binder from service manager: "
 78               << Status::fromStatusT(status).toString8();
 79    return ExitWhenIdle(1);
 80  }
 81  //以下是根据参数 调用相应服务端的方法 
 82  //调用服务的suspend方法
 83  if (FLAGS_suspend) {
 84    return ExitWhenIdle(service_->suspend());
 85  }
 86  //调用服务的resume方法
 87  if (FLAGS_resume) {
 88    return ExitWhenIdle(service_->resume());
 89  }
 90  //调用服务的cancel方法
 91  if (FLAGS_cancel) {
 92    return ExitWhenIdle(service_->cancel());
 93  }
 94  //调用服务的resetStatus方法
 95  if (FLAGS_reset_status) {
 96    return ExitWhenIdle(service_->resetStatus());
 97  }
 98  //注册回调函数UECallback到服务端service_
 99  if (FLAGS_follow) {
100    // Register a callback object with the service.
101    callback_ = new UECallback(this);
102    bool bound;
103    if (!service_->bind(callback_, &bound).isOk() || !bound) {
104      LOG(ERROR) << "Failed to bind() the UpdateEngine daemon.";
105      return 1;
106    }
107    keep_running = true;
108  }
109  //参数为update,调用服务applyPayload方法,传入对应的参数
110  if (FLAGS_update) {
111    //将header以空格\n进行分割放入string类型的容器中
112    std::vector<std::string> headers = base::SplitString(
113        FLAGS_headers, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
114    //声明and_headers string类型的容器
115    std::vector<android::String16> and_headers;
116    //通过push_back方法以键值对的方式放入到and_headers中
117    for (const auto& header : headers) {
118      and_headers.push_back(android::String16{header.data(), header.size()});
119    }
120    //将praload offset size and_headers 参数传入服务端的applyPayload方法进行升级
121    Status status = service_->applyPayload(
122        android::String16{FLAGS_payload.data(), FLAGS_payload.size()},
123        FLAGS_offset,
124        FLAGS_size,
125        and_headers);
126    //如果升级失败,调用ExitWhenIdle传入status退出
127    if (!status.isOk())
128      return ExitWhenIdle(status);
129  }
130  //我对这个标志位不是很理解,意思相当于如果keep_running不为真,那么编译完成了并退出?
131  if (!keep_running)
132    return ExitWhenIdle(EX_OK);
133
134  // When following updates status changes, exit if the update_engine daemon
135  // dies.//当更新状态发生变化时,如果update_engine守护程序退出死亡。
136  //如果服务端进程终止了,相应的也会停止客户端进程
137  android::BinderWrapper::Create();
138  android::BinderWrapper::Get()->RegisterForDeathNotifications(
139      android::os::IUpdateEngine::asBinder(service_),
140      base::Bind(&UpdateEngineClientAndroid::UpdateEngineServiceDied,
141                 base::Unretained(this)));
142
143  return EX_OK;
144}

UpdateEngineServiceDied方法

1update_engine_client_android.cc
2
3//如果服务挂了,停止客户端并退出
4void UpdateEngineClientAndroid::UpdateEngineServiceDied() {
5  LOG(ERROR) << "UpdateEngineService died.";
6  QuitWithExitCode(1);
7}

这就是update_engine_client的大致代码流程

 

二、framwork层 应用接口

首先应用方面要处理的借口和回调方法:

1、在app中设置一个callback,用来接收update_engine 升级状态和完成的通知

源代码位置:framwork/base/core/java/android/os/UpdateEngine.java

 

继承UpdateEngineCallback 重写onStatusUpdate 和 onPayloadApplicationComplete 方法

onStatusUpdate方法用于获取升级的状态比如升级的百分比或者错误

onPayloadApplicationComplete被调用当升级完整或者返回错误状态的时候

 

完成的列表或者错误的在./system/update_engine/common/error_code.h

 

2、app应用调取applyUpdate方法

pubic void applyPayload(String url,long offset,long size,String[] headerKeyValuePairs)

url:升级包(Payload)的路径,ab升级只能使用内置存储,必须在目录 /data/ota_package/xxx 而且需要以file://开头,比如file://data/ota_package/update.zip

update engine只接受固定的路径/data/ota_package/update.zip,其他路径和sdcard不支持

app需要获取se权限区操作使用这个路径:

allow your_app ota_package_file:dir { read open write create remove_name search rename add_name getattr };

allow your_app ota_otapackage_file:file{ read write create open rename getattr unlink };

 

offset:这是payload 在update.zip中的偏移量,需要从升级包文件中计算出来

 

Size:这是payload文件的大小,可以在payload_properties.txt中找到

 

headerKeyValuePairs:这是metadata,可以在升级包中的payload_properties.txt中找到,

headerKeyValuePairs参数 时用来传输metadata数据给update_engine服务端,存储在payload_properties.txt,通过脚本system/update_engine/scripts/brillo_update_payload

 生成,数据格式如下:

String[] pairs = {

              "FILE_HASH=f1KT8nZAvNCx7hesGI0xaqVm9CIWzQvXGfg2T2Cp+ME=",

              "FILE_SIZE=781070526",

              "METADATA_HASH=lMosFzUjtB1ODkiSTw4xgNt6WkYuGV70GzTkdNTtlMU=",

              "METADATA_SIZE=89254"

};

我们先看下framwork 层对应的代码内容

./framwork/base/core/java/android/os/UpdateEngineCallback.java

 

 1/**
 2 * Callback function for UpdateEngine. Used to keep the caller up to date
 3 * with progress, so the UI (if any) can be updated.
 4 *
 5 * The APIs defined in this class and UpdateEngine class must be in sync with
 6 * the ones in
 7 * system/update_engine/binder_bindings/android/os/IUpdateEngine.aidl and
 8 * system/update_engine/binder_bindings/android/os/IUpdateEngineCallback.aidl.
 9 *
10 * {@hide}
11 */
12@SystemApi
13//  UpdateEngine的回调函数。 用户调用app保持最新状态进度,因此可以更新UI,这是抽象函数
14//  app需要继承UpdateEngineCallback,并重写其中的方法
15public abstract class UpdateEngineCallback {
16
17    /**
18     * Invoked when anything changes. The value of {@code status} will
19     * be one of the values from {@link UpdateEngine.UpdateStatusConstants},
20     * and {@code percent} will be valid [TODO: in which cases?].
21     */
22    @SystemApi//监听升级状态
23    public abstract void onStatusUpdate(int status, float percent);
24
25    /**
26     * Invoked when the payload has been applied, whether successfully or
27     * unsuccessfully. The value of {@code errorCode} will be one of the
28     * values from {@link UpdateEngine.ErrorCodeConstants}.
29     */
30    @SystemApi//监听升级结果
31    public abstract void onPayloadApplicationComplete(int errorCode);
32}

./framwork/base/core/java/android/os/UpdateEngine.java

  1@SystemApi
  2public class UpdateEngine {
  3    //定义文件log的tag
  4    private static final String TAG = "UpdateEngine";
  5    //定义update_engine service的名称
  6    private static final String UPDATE_ENGINE_SERVICE = "android.os.UpdateEngineService";
  7
  8    /**
  9     * Error code from the update engine. Values must agree with the ones in
 10     * system/update_engine/common/error_code.h.
 11     */
 12    @SystemApi //升级结果常量,这些值于服务端的errorcode相同
 13    public static final class ErrorCodeConstants {
 14        public static final int SUCCESS = 0;
 15        public static final int ERROR = 1;
 16        public static final int FILESYSTEM_COPIER_ERROR = 4;
 17        public static final int POST_INSTALL_RUNNER_ERROR = 5;
 18        public static final int PAYLOAD_MISMATCHED_TYPE_ERROR = 6;
 19        public static final int INSTALL_DEVICE_OPEN_ERROR = 7;
 20        public static final int KERNEL_DEVICE_OPEN_ERROR = 8;
 21        public static final int DOWNLOAD_TRANSFER_ERROR = 9;
 22        public static final int PAYLOAD_HASH_MISMATCH_ERROR = 10;
 23        public static final int PAYLOAD_SIZE_MISMATCH_ERROR = 11;
 24        public static final int DOWNLOAD_PAYLOAD_VERIFICATION_ERROR = 12;
 25        public static final int UPDATED_BUT_NOT_ACTIVE = 52;
 26    }
 27
 28    /**
 29     * Update status code from the update engine. Values must agree with the
 30     * ones in system/update_engine/client_library/include/update_engine/update_status.h.
 31     */
 32    @SystemApi //升级进度常量,这些值于服务端的UpdateStatu相同
 33    public static final class UpdateStatusConstants {
 34        public static final int IDLE = 0;
 35        public static final int CHECKING_FOR_UPDATE = 1;
 36        public static final int UPDATE_AVAILABLE = 2;
 37        public static final int DOWNLOADING = 3;
 38        public static final int VERIFYING = 4;
 39        public static final int FINALIZING = 5;
 40        public static final int UPDATED_NEED_REBOOT = 6;
 41        public static final int REPORTING_ERROR_EVENT = 7;
 42        public static final int ATTEMPTING_ROLLBACK = 8;
 43        public static final int DISABLED = 9;
 44    }
 45
 46    private IUpdateEngine mUpdateEngine;
 47    private IUpdateEngineCallback mUpdateEngineCallback = null;
 48    private final Object mUpdateEngineCallbackLock = new Object();
 49
 50    /**
 51     * Creates a new instance.当我们new 一个UpdateEngine对象时,service也被创建出来
 52     */
 53    @SystemApi
 54    public UpdateEngine() {
 55        mUpdateEngine = IUpdateEngine.Stub.asInterface(
 56                ServiceManager.getService(UPDATE_ENGINE_SERVICE));
 57    }
 58
 59    /**
 60     * Prepares this instance for use. The callback will be notified on any
 61     * status change, and when the update completes. A handler can be supplied
 62     * to control which thread runs the callback, or null.
 63     */
 64    @SystemApi 
 65    public boolean bind(final UpdateEngineCallback callback, final Handler handler) {
 66        synchronized (mUpdateEngineCallbackLock) {
 67            mUpdateEngineCallback = new IUpdateEngineCallback.Stub() {
 68                @Override
 69                public void onStatusUpdate(final int status, final float percent) {
 70                    if (handler != null) {
 71                        handler.post(new Runnable() {
 72                            @Override
 73                            public void run() {
 74                                callback.onStatusUpdate(status, percent);
 75                            }
 76                        });
 77                    } else {
 78                        callback.onStatusUpdate(status, percent);
 79                    }
 80                }
 81
 82                @Override
 83                public void onPayloadApplicationComplete(final int errorCode) {
 84                    if (handler != null) {
 85                        handler.post(new Runnable() {
 86                            @Override
 87                            public void run() {
 88                                callback.onPayloadApplicationComplete(errorCode);
 89                            }
 90                        });
 91                    } else {
 92                        callback.onPayloadApplicationComplete(errorCode);
 93                    }
 94                }
 95            };
 96
 97            try {
 98                //绑定mUpdateEngineCallback到服务端
 99                return mUpdateEngine.bind(mUpdateEngineCallback);
100            } catch (RemoteException e) {
101                throw e.rethrowFromSystemServer();
102            }
103        }
104    }
105
106    /**
107     * Equivalent to {@code bind(callback, null)}.
108     */
109    @SystemApi //第三方应用调取 用户绑定服务
110    public boolean bind(final UpdateEngineCallback callback) {
111        return bind(callback, null);
112    }
113
114    /**
115     * Applies the payload found at the given {@code url}. For non-streaming
116     * updates, the URL can be a local file using the {@code file://} scheme.
117     *
118     * <p>The {@code offset} and {@code size} parameters specify the location
119     * of the payload within the file represented by the URL. This is useful
120     * if the downloadable package at the URL contains more than just the
121     * update_engine payload (such as extra metadata). This is true for
122     * Google's OTA system, where the URL points to a zip file in which the
123     * payload is stored uncompressed within the zip file alongside other
124     * data.
125     *
126     * <p>The {@code headerKeyValuePairs} parameter is used to pass metadata
127     * to update_engine. In Google's implementation, this is stored as
128     * {@code payload_properties.txt} in the zip file. It's generated by the
129     * script {@code system/update_engine/scripts/brillo_update_payload}.
130     * The complete list of keys and their documentation is in
131     * {@code system/update_engine/common/constants.cc}, but an example
132     * might be:
133     * <pre>
134     * String[] pairs = {
135     *   "FILE_HASH=lURPCIkIAjtMOyB/EjQcl8zDzqtD6Ta3tJef6G/+z2k=",
136     *   "FILE_SIZE=871903868",
137     *   "METADATA_HASH=tBvj43QOB0Jn++JojcpVdbRLz0qdAuL+uTkSy7hokaw=",
138     *   "METADATA_SIZE=70604"
139     * };
140     * </pre>
141     */
142    @SystemApi 具体执行升级的接口
143    public void applyPayload(String url, long offset, long size, String[] headerKeyValuePairs) {
144        try {
145            //调用服务端的applyPayload方法执行升级
146            mUpdateEngine.applyPayload(url, offset, size, headerKeyValuePairs);
147        } catch (RemoteException e) {
148            throw e.rethrowFromSystemServer();
149        }
150    }
151
152    /**
153     * Permanently cancels an in-progress update.
154     *
155     * <p>See {@link #resetStatus} to undo a finshed update (only available
156     * before the updated system has been rebooted).
157     *
158     * <p>See {@link #suspend} for a way to temporarily stop an in-progress
159     * update with the ability to resume it later.
160     */
161    @SystemApi //调用服务端cancel方法
162    public void cancel() {
163        try {
164            mUpdateEngine.cancel();
165        } catch (RemoteException e) {
166            throw e.rethrowFromSystemServer();
167        }
168    }
169
170    /**
171     * Suspends an in-progress update. This can be undone by calling
172     * {@link #resume}.
173     */
174    @SystemApi //调用服务端suspend方法
175    public void suspend() {
176        try {
177            mUpdateEngine.suspend();
178        } catch (RemoteException e) {
179            throw e.rethrowFromSystemServer();
180        }
181    }
182
183    /**
184     * Resumes a suspended update.
185     */
186    @SystemApi //调用服务端resume方法
187    public void resume() {
188        try {
189            mUpdateEngine.resume();
190        } catch (RemoteException e) {
191            throw e.rethrowFromSystemServer();
192        }
193    }
194
195    /**
196     * Resets the bootable flag on the non-current partition and all internal
197     * update_engine state. This can be used after an unwanted payload has been
198     * successfully applied and the device has not yet been rebooted to signal
199     * that we no longer want to boot into that updated system. After this call
200     * completes, update_engine will no longer report
201     * {@code UPDATED_NEED_REBOOT}, so your callback can remove any outstanding
202     * notification that rebooting into the new system is possible.
203     */
204    @SystemApi  //调用服务端resetStatus方法
205    public void resetStatus() {
206        try {
207            mUpdateEngine.resetStatus();
208        } catch (RemoteException e) {
209            throw e.rethrowFromSystemServer();
210        }
211    }
212
213    /**
214     * Unbinds the last bound callback function.
215     */
216    @SystemApi //解除绑定callback的监听
217    public boolean unbind() {
218        synchronized (mUpdateEngineCallbackLock) {
219            if (mUpdateEngineCallback == null) {
220                return true;
221            }
222            try {
223                boolean result = mUpdateEngine.unbind(mUpdateEngineCallback);
224                mUpdateEngineCallback = null;
225                return result;
226            } catch (RemoteException e) {
227                throw e.rethrowFromSystemServer();
228            }
229        }
230    }
231
232    /**
233     * Verifies that a payload associated with the given payload metadata
234     * {@code payloadMetadataFilename} can be safely applied to ths device.
235     * Returns {@code true} if the update can successfully be applied and
236     * returns {@code false} otherwise.
237     *
238     * @param payloadMetadataFilename the location of the metadata without the
239     * {@code file://} prefix.
240     */
241    @SystemApi  //校验Payload的元数据
242    public boolean verifyPayloadMetadata(String payloadMetadataFilename) {
243        try {
244            return mUpdateEngine.verifyPayloadApplicable(payloadMetadataFilename);
245        } catch (RemoteException e) {
246            throw e.rethrowFromSystemServer();
247        }
248    }
249}

看完这两两个文件的代码,相信android的小伙伴都知道该怎么处理了,我这里只说一下大致流程

1、创建类abtest继承UpdateEngineCallback

2、创建UpdateEngine的对象mUpdateEngine,创建后服务开启

3、使用mUpdateEngine.bind(abtest) 因为bind方法时接受的callback对象,而我们创建的类继承了callback,传入当前类的对象即可

4、调用applyPayload方法具体执行升级

5、在重写的onStatusUpdate(int status, float percent)方法中根据拿到的状态执行进度逻辑

      在重写的onPayloadApplicationComplete(int errorCode);方法中执行升级完成后的逻辑

 

两种情况其实相差不大,都是绑定监听,调用服务端相同的方法进行升级,好了,如果把AB升级理解为一栋别墅,我们现在已经开启了院子的大门,里面放了一个update_engine等待我们去拜访,后面将分析这个最重要的模块

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
NOTE: > Executing update_desktop_database intercept ... NOTE: > Executing update_gtk_immodules_cache intercept ... NOTE: Exit code 1. Output: /home/wu/g2l/build-niicl-nom-r001l/tmp/work/nom_r001l-niic-linux/core-image-weston/1.0-r0/intercept_scripts-b51052418cd1de15aa19deeae9844eade47e1e2e32985d114ac9c6c1afe994aa/update_gtk_immodules_cache: line 15: /home/wu/g2l/build-niicl-nom-r001l/tmp/work/nom_r001l-niic-linux/core-image-weston/1.0-r0/rootfs/usr/lib64/gtk-3.0/3.0.0/immodules.cache: No such file or directory chown: cannot access '/home/wu/g2l/build-niicl-nom-r001l/tmp/work/nom_r001l-niic-linux/core-image-weston/1.0-r0/rootfs/usr/lib64/gtk-3.0/3.0.0/immodules.cache': No such file or directory ERROR: The postinstall intercept hook 'update_gtk_immodules_cache' failed, details in /home/wu/g2l/build-niicl-nom-r001l/tmp/work/nom_r001l-niic-linux/core-image-weston/1.0-r0/temp/log.do_rootfs NOTE: > Executing update_desktop_database intercept ... NOTE: > Executing update_gtk_immodules_cache intercept ... NOTE: Exit code 1. Output: /home/wu/g2l/build-niicl-nom-r001l/tmp/work/nom_r001l-niic-linux/core-image-weston/1.0-r0/intercept_scripts-b51052418cd1de15aa19deeae9844eade47e1e2e32985d114ac9c6c1afe994aa/update_gtk_immodules_cache: line 15: /home/wu/g2l/build-niicl-nom-r001l/tmp/work/nom_r001l-niic-linux/core-image-weston/1.0-r0/rootfs/usr/lib64/gtk-3.0/3.0.0/immodules.cache: No such file or directory chown: cannot access '/home/wu/g2l/build-niicl-nom-r001l/tmp/work/nom_r001l-niic-linux/core-image-weston/1.0-r0/rootfs/usr/lib64/gtk-3.0/3.0.0/immodules.cache': No such file or directory ERROR: The postinstall intercept hook 'update_gtk_immodules_cache' failed, details in /home/wu/g2l/build-niicl-nom-r001l/tmp/work/nom_r001l-niic-linux/core-image-weston/1.0-r0/temp/log.do_rootfs DEBUG: Python function do_rootfs finished如何解决
07-20
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值