本编将从两个方面分析客户端,原生测试模块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等待我们去拜访,后面将分析这个最重要的模块

3267





