近期猛然发现公司的项目都已经换成了AB升级,AB升级之前一直有所了解,只是一直都没有去仔细查看过其具体升级流程,这两天抽空捋了捋,简单整理下。
AB升级(谷歌官网叫法无缝更新)是自android7.0开始新增的一种android设备升级方式,只是这种方式对设备存储要求高,所以之前没有怎么被国内手机厂商采用。
简而言之:系统同时存在两套system分区,一套处于休眠状态不可使用,一套处于使用状态,两者通过slot的概念来做区分,在设备启动引导阶段通过特殊标记位确定启动哪个system,当有可用升级版本时候,客户端将升级包下载下来,或者将下载地址请求下来,然后通过update_engine将当前没有在使用的一套system升级到最新版本,然后修改启动标志位,在下次启动的时候,就进入升级到最新版本的那套system系统,这样做的好处就是省去了recovery升级过程的耗时,规避了recovery升级过程中发生意外中断导致设备无法开机的风险。现将其主要逻辑做简单整理归纳
AB升级的主要实现过程在udate_engine中,主要代码集中在/system/update_engine路径下
主要分为两部分:
1.update_engine的初始化过程
2.java层调用升级接口执行升级过程
1.update_engine的初始化过程
首先查看目录下的Android.bp,这里只列举重点内容
// update_engine (type: executable)
// ========================================================
// update_engine daemon.
cc_binary {
name: "update_engine",
defaults: [
"ue_defaults",
"libupdate_engine_android_exports",
],
static_libs: ["libupdate_engine_android"],
required: [
"cacerts_google",
"otacerts",
],
srcs: ["main.cc"],
init_rc: ["update_engine.rc"],
}
update_engine.rc内容如下:
service update_engine /system/bin/update_engine --logtostderr --logtofile --foreground
class late_start
user root
group root system wakelock inet cache media_rw
writepid /dev/cpuset/system-background/tasks /dev/blkio/background/tasks
disabled
on property:ro.boot.slot_suffix=*
enable update_engine
update_engine服务在init进程中启动,启动后运行main.cc中的main函数:
int main(int argc, char** argv) {
......运行UpdateEngineDaemon,这里用了c++11的新特性默认构造函数
chromeos_update_engine::UpdateEngineDaemon update_engine_daemon;
int exit_code = update_engine_daemon.Run();
chromeos_update_engine::Subprocess::Get().FlushBufferedLogsAtExit();
LOG(INFO) << "A/B Update Engine terminating with exit code " << exit_code;
return exit_code;
}
UpdateEngineDaemon 继承自 brillo::Daemon (external\libbrillo\brillo\daemons)
会运行到UpdateEngineDaemon::OnInit中:
system\update_engine\daemon.cc
int UpdateEngineDaemon::OnInit() {
subprocess_.Init(this);
int exit_code = Daemon::OnInit();
if (exit_code != EX_OK)
return exit_code;
#if USE_BINDER
android::BinderWrapper::Create();
binder_watcher_.Init();
#endif // USE_BINDER
//这里初始化daemon_state_,因为是USE_BINDER,所以初始化结果是DaemonStateAndroid
#if USE_OMAHA
RealSystemState* real_system_state = new RealSystemState();
daemon_state_.reset(real_system_state);
LOG_IF(ERROR, !real_system_state->Initialize())
<< "Failed to initialize system state.";
#else // !USE_OMAHA
DaemonStateAndroid* daemon_state_android = new DaemonStateAndroid();
daemon_state_.reset(daemon_state_android);
LOG_IF(ERROR, !daemon_state_android->Initialize())
<< "Failed to initialize system state.";
#endif // USE_OMAHA
//这里初始化binder_service_,最终将BinderUpdateEngineBrilloService注册到ServiceManager中,服务名android.os.UpdateEngineService
#if USE_BINDER
// Create the Binder Service.
#if USE_OMAHA
binder_service_ = new BinderUpdateEngineBrilloService{real_system_state};
#else // !USE_OMAHA
binder_service_ = new BinderUpdateEngineAndroidService{
daemon_state_android->service_delegate()};
#endif // USE_OMAHA
auto binder_wrapper = android::BinderWrapper::Get();
if (!binder_wrapper->RegisterService(binder_service_->ServiceName(),
binder_service_)) {
LOG(ERROR) << "Failed to register binder service.";
}
daemon_state_->AddObserver(binder_service_.get());
#endif // USE_BINDER
#if USE_DBUS
// Create the DBus service.
dbus_adaptor_.reset(new UpdateEngineAdaptor(real_system_state));
daemon_state_->AddObserver(dbus_adaptor_.get());
dbus_adaptor_->RegisterAsync(base::Bind(&UpdateEngineDaemon::OnDBusRegistered,
base::Unretained(this)));
LOG(INFO) << "Waiting for DBus object to be registered.";
#else //开始执行升级
daemon_state_->StartUpdater();
#endif // USE_DBUS
return EX_OK;
}
OnInit方法中执行的主要操作就是于binder服务关联起来,将BinderUpdateEngineBrilloService以android.os.UpdateEngineService的名称注册到serviceManager中,
而BinderUpdateEngineBrilloService的执行又是放到了UpdateAttempterAndroid中,一些主要的执行类关系图如下: