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

Android P update_engine分析(四) --update_engine_client的工作 当AB系统升级时,有两种方式来调用updateengine,来实现升级,一种方法是直接执行shell命令,调用 update_engine_client,带参数来实现升级,另一种方式是应用层直接调用UpdateEngine的applyPayload方法来升级。 update_engine_client 带参升级 shell命令调用update_engine_client带参数去升级,具体如下: update_engine_client --payload=file:///sdcard/payload.bin 阅读详情

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

Android A/B System OTA分析(五)客户端参数 AB OTA 阅读详情

相关推荐

深入解析A/B升级中的update_engine核心模块与编译流程

本文深入解析了Android A/B系统升级中的核心服务模块update_engine及其编译流程。文章从Android.mk构建脚本入手,详细拆解了核心静态库、关键可执行文件(如update_engine守护进程、update_engine_sideload)的依赖关系与职责,并阐述了它们在完整A/B升级流程中的协作机制,为开发者理解和定制升级系统提供了清晰指南。

plum99的博客 738

Android UpdateEngine 模块分析(三)升级触发以及Action机制介绍

前面分析了 UpdateEngine 模块的编译和启动流程,对于 UpdateEngine 模块已经有了初步的了解,接下来我们从升级的功能出发,分析 UpdateEngine 的升级过程,升级过程的内容非常的多,准备从 UpdateEngine 的 Action 机制开始分析,UpdateEngine 的升级过程有很多步骤,每一个步骤由一个 Action 去控制。因此,我们先说明 UpdateEngine 模块的 Action 机制,并从升级的触发方式以及实现流程展开描述。

Yang_Mao_Shan的博客 8386

update_engine简介

近期猛然发现公司的项目都已经换成了AB升级,AB升级之前一直有所了解,只是一直都没有去仔细查看过其具体升级流程,这两天捋了捋,简单整理下。 AB升级(谷歌官网叫法无缝更新)是自android7.0开始新增的一种android设备升级方式,只是这种方式对设备存储要求高,所以之前没有怎么被国内手机厂商采用。 简而言之:系统同时存在两套system分区,一套处于休眠状态不可使用,一套处于使用状态,两者通过slot的概念来做区分,在设备启动引导阶段通过特殊标记位确定启动哪个system,当有可用升级版本时候,客

搬砖的老牛 5765

OTA A/B 分区升级 update_engine简介

现将其主要逻辑做简单整理归纳。cmd参数就是一开始传过来的command,这里用到了brillo/process.cc来执行命令,这里不再继续跟进了,update_engine大致的升级流程到这里就完成了,但还是有很多方面暂时没有涉及,一些详细的过程也没有去更进一步的去分析跟进,留待以后有时间或者遇到相关问题再去做进一步分析。整个升级的执行过程都在ApplyPayload方法中进行了,先是检查了参数和当前升级状态,然后构建了install_plan_,它的作用就是打印信息,将。

Venus 的博客 6188

Android A/B升级实战:从update_engine模块拆解到避坑指南

本文深入拆解了Android A/B升级的核心模块update_engine,详细剖析了libpayload_consumer、libupdate_engine_android等静态库的功能与依赖关系,并提供了从编译配置到实战调试的完整避坑指南,帮助开发者高效解决升级过程中的常见问题。

weixin_28365523的博客 170

深入解析Android update_engine_client的Binder通信机制与升级流程

本文深入解析了Android OTA升级的核心机制,重点剖析了update_engine_client命令行工具如何通过Binder进程间通信(IPC)与UpdateEngineService服务交互。文章详细阐述了从参数解析、Binder接口调用到服务端构建升级流水线(Action)的完整流程,揭示了Android系统无缝升级(A/B升级)背后的技术原理与实现细节。

pca5navigator的博客 663

四、A/B 升级update_engine分析-服务端启动

以下我们将分析AB升级的核心内容 update_engine服务端,我们还是一样,看下该模块的编译文件和依赖。 一、相关依赖 1LOCAL_MODULE := update_engine 2LOCAL_SRC_FILES := \ 3 main.cc 4LOCAL_STATIC_LIBRARIES += \ 5 libupdate_engine_android ...

李标标的博客 2272

Android源码分析(十六)----adb shell 命令进行OTA升级

一: 进入shell命令界面 adb shell 二:创建目录/cache/recovery mkdir /cache/recovery 如果系统中已有此目录,则会提示已存在。 三: 修改文件夹权限 chmod -R 777 /cache/recovery 四: 把ota文件路径写入/cache/recovery/command文件中 echo "–update_package=系统ota升级...

—莫言— 2053

Android A/B System OTA分析(四)系统的启动和升级

Android从7.0开始引入新的OTA升级方式,`A/B System Updates`,这里将其叫做`A/B`系统,涉及的内容较多,分多篇对`A/B`系统的各个方面进行分析。本文为第四篇,系统的启动和升级。 本文为洛奇看世界(guyongqiangx)原创,转载请注明出处。 文章链接:https://blog.youkuaiyun.com/guyongqiangx/article/details/72604355

洛奇看世界 3万+

Android Update Engine分析(七) DownloadAction之FileWriter

Android Update Engine分析(七) DownloadAction之FileWriter 本系列到现在为止的共有六篇,分别分析分析了Makefile,Update Engine的客户端、服务端及Action机制的细节: Android Update Engine分析(一)Makefile Android Update Engine分析(二)Protobuf和AIDL文件 Andr......

洛奇看世界 9432

Android Update Engine分析(三)客户端进程

Android Update Engine分析(三)客户端update_engine_client 技术文章直入主题,展示结论,容易让人知其然,不知其所以然。 我个人更喜欢在文章中展示如何阅读代码,逐步分析解决问题的思路和过程。这样的思考比知道结论更重要,希望我的分析能让你有所收获。 前面两篇分别分析了Makefile,Protobuf和AIDL相关文件,从本篇开始正式深入功能实...

洛奇看世界 1万+

五、A/B 升级update_engine分析-UpdateAttempterAndroid

上一篇我们讲到了服务端启动的流程,本篇主要讲解主要升级流程,UpdateAttempterAndroid类包含的内容较多,所以单独讲解,这个文件看了很长时间,大概方法都已经了解,但是想了很久从哪儿开始梳理这个流程,不仅仅是我能看懂,而且能讲出来的很清晰,这是我想做到的,别问,问就是重点 一、update_attempter_android.h 简要分析 1、继承和构造函数 ...

李标标的博客 3558

Android Update Engine 分析(二十一)Android A/B 更新过程

我的第一篇 A/B 系统分析文章《Android A/B System OTA分析(一)概览》从总体上介绍了什么是 A/B 系统,A/B 系统如何进行升级切换,应该是不少人 A/B 系统升级的入门读物。从那之后,我陆续写过几十篇 Android A/B 系统升级的文章(到现在也还有很多话题没有写),但每一篇都只分析了很小的一部分,要不就是分析功能代码,要不就是分析处理流程,要不就是演示工具使用。似乎从来没有一篇从总体角度上,全面又很详细介绍 Android A/B 系统升级。幸运的是,Android 官方对

洛奇看世界 3447

Android Update Engine 分析(二十五)升级状态 prefs 是如何保存的?

本系列到现在为止一共二十四篇,前面十七篇基本上就是阅读 update engine 的核心代码和函数,第十七篇以后开始按照话题进行分析。在前面十七篇中,把核心功能代码过了一遍,但仍然有不少功能代码还没分析过。例如,Update Engine 的升级状态数据时如何保存的?系统到底定义了哪些 prefs 数据?本文就管理 Update Engine 状态的 Prefs 类进行详细分析。

洛奇看世界 1848

Android Update Engine 分析(十五) FullUpdateGenerator 策略

生成 payload 时,会选择不同的策略去遍历每一个分区的每一个 block 生成相应的 Operation 数据: 1. 差分升级的情况下,如果 version.minor = 1, 则使用 InplaceGenerator 策略 2. 差分升级的情况下,其它情况使用 ABGenerator 策略 3. 全量升级情况, 使用 FullUpdateGenerator 策略 本篇分析最简单的 FullUpdateGenerator 策略

洛奇看世界 2982

Android Update Engine分析(十四) 生成 payload 数据

生成 payload 数据是 `delta_generator` 工具最主要的功能,当我准备重新更新这一些列文章时,一开始就想写这个的,不过因为太久没看,不记得 payload 细节了,更无从从细节上分析。所以就先写一些简单的操作,等熟悉了再开始写。经过前面篇的分析了解 payload 结构,现在是时候来解决这个问题了。

洛奇看世界 3914

Android OTA 升级专栏文章导读

从 2017 年起,我陆续写了一些 Android OTA 升级相关的文章,主要介绍从 Android 7.1 开始引入的 A/B 升级系统,包括从早前的 A/B 系统,到后来的动态分区,再到最近的虚拟 A/B 分区,以及最新的一些 Android OTA 话题。毫不夸张的说,这是目前全网关于 Android OTA 升级最系统,最全面的专栏,没有之一。

洛奇看世界 1万+

均值回归 高频交易_基于布林带的均值回归交易策略

BOLL指标是美国股市分析家约翰·布林根据统计学中的标准差原理设计出来的一种非常简单实用的技术分析指标。一般而言,股价的运动总是围绕某一价值中枢(如均线、成本线等)在一定的范围内变动,布林线指标正是在上述条件的基础上,引进了“股价通道”的概念,其认为股价通道的宽窄随着股价波动幅度的大小而变化,而且股价通道又具有变异性,它会随着股价的变化而自动调整。由于之前大部分交易策略都是选股或者趋势追踪的择时,...

weixin_42528534的博客 1458
上一篇: 一、A/B升级之系统image的生成
下一篇: 四、A/B 升级update_engine分析-服务端启动
李标标
博客等级 码龄11年 124粉丝 43原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值