前言
前一章节分析了 UpdateEngine 模块的编译文件,从编译中分析主要模块。本章节将从 UpdateEngine 模块的主要功能文件 update_engine 开始,分析 UpdateEngine 模块的服务启动流程,梳理 UpdateEngine 服务是如何启动以及启动中完成了什么工作~
上一篇:Android UpdateEngine 模块分析(一)模块编译介绍
下一篇:Android UpdateEngine 模块分析(三)升级触发以及Action机制介绍
正文
UpdateEngine 模块是 Android 中的升级模块,其主要的核心功能是系统的 A/B 升级,理解了 UpdateEngine 就理解了在 Android 中 A/B 升级是如何运行的。基于上一章节编译分析,那么接下来对重要可执行二进制文件 update_engine 进行分析,涉及 UpdateEngine 模块服务的启动以及启动过程中的准备工作~
1、update_engine模块定义
updateengine 可执行文件是 UpdateEngine 服务模块的入口文件,既然是分析 UpdateEngine 模块功能,我们先从 udpateengine 文件的定义入手,进而详细分析~
// 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"],
srcs: ["main.cc"],
init_rc: ["update_engine.rc"],
}
上述代码是 update_engine 在 Android.mk 中的定义,代码中定义了文件名“update_engine”,默认包含模块“ue_defaults、libupdate_engine_android_exports”,引用静态库“libupdate_engine_android”,入口文件“main.cc”,rc文件”update_engine.rc“。
2、UpdateEngine模块服务
UpdateEngine 模块在 Android 架构中可以理解为一个 Hal 服务,在 Android 的启动流程中,init 进程会通过解析 rc 文件的方式执行模块功能的可执行文件,进而把服务启动。UpdateEngine 模块也是如此,从可执行文件 update_engine 的定义中,已经指定了 rc 启动文件为 update_engine.rc,入口文件为 main.cc。
2.1 rc文件
update_engine.rc 文件,文件路径在”android/system/update_engine“下,内容如下:
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
disabled
on property:ro.boot.slot_suffix=*
enable update_engine
rc 文件中定义了一个服务 updat_engine,这个服务的可执行文件是设备的 /system/bin/update_engine,对应这个 service 可执行文件在系统中的位置,”–logtostderr --logtofile --foreground“是启动服务时所传入的参数,class 代表着 update_engine 服务属于 late_start,这个是在 init 中所定义的,基于不同的服务指定不同的启动阶段,user 为 root 用户,group 为组归属,writepid 为当 fork 一个子进程时,写子进程的 pid 到一个指定的路径”/dev/cpuset/system-background/tasks“下,disabled 为 Service 不会在 rc 中自动启动,需要在代码中使用 property_set() 方法来启动,例如:property_set(“ctl.start”, “wifi_dhcpcd”),启动 wifi_dhcpcd 服务。
定义了一个 property 属性触发器,当系统设置了 ro.boot.slot_suffix 属性时,将 update_engine 的 disabled 属性变更为 enabled,且 start。
2.2 UpdateEngine服务启动流程
从编译文件中可以确认,update_engine 可执行程序的入口文件是 main.cc,那我们去分析下 main.cc ~
int main(int argc, char** argv) {
DEFINE_bool(logtofile, false, "Write logs to a file in log_dir.");
DEFINE_bool(logtostderr,
false,
"Write logs to stderr instead of to a file in log_dir.");
DEFINE_bool(foreground, false, "Don't daemon()ize; run in foreground.");
chromeos_update_engine::Terminator::Init();
brillo::FlagHelper::Init(argc, argv, "A/B Update Engine");
// We have two logging flags "--logtostderr" and "--logtofile"; and the logic
// to choose the logging destination is:
// 1. --logtostderr --logtofile -> logs to both
// 2. --logtostderr -> logs to system debug
// 3. --logtofile or no flags -> logs to file
bool log_to_system = FLAGS_logtostderr;
bool log_to_file = FLAGS_logtofile || !FLAGS_logtostderr;
chromeos_update_engine::SetupLogging(log_to_system, log_to_file);
if (!FLAGS_foreground)
PLOG_IF(FATAL, daemon(0, 0) == 1) << "daemon() failed";
LOG(INFO) << "A/B Update Engine starting";
// xz-embedded requires to initialize its CRC-32 table once on startup.
xz_crc32_init();
// Ensure that all written files have safe permissions.
// This is a mask, so we _block_ all permissions for the group owner and other
// users but allow all permissions for the user owner. We allow execution
// for the owner so we can create directories.
// Done _after_ log file creation.
umask(S_IRWXG | S_IRWXO);
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;
}
从入口文件中,我们可以提取出比较关键的步骤如下:
A chromeos_update_engine::Terminator::Init();
B brillo::FlagHelper::Init(argc, argv, “A/B Update Engine”);
C chromeos_update_engine::SetupLogging(log_to_system, log_to_file);
D xz_crc32_init();
E umask(S_IRWXG | S_IRWXO);
F chromeos_update_engine::UpdateEngineDaemon update_engine_daemon;
int exit_code = update_engine_daemon.Run();
G chromeos_update_engine::Subprocess::Get().FlushBufferedLogsAtExit();
那么我们只要从这些步骤的功能出发,也就了解升级模块 update_engine 的启动流程了~
2.2.1 启动日志
启动过程中,update_engine 模块的日志如下:
01-01 06:19:25.229 2457 2457 I update_engine: [0101/061925.228261:INFO:main.cc(182)] Chrome OS Update Engine starting
01-01 06:19:25.250 2457 2457 I update_engine: [0101/061925.250380:INFO:boot_control_android.cc(64)] Loaded boot control hidl hal.
01-01 06:19:25.250 2457 2457 I update_engine: [0101/061925.250576:INFO:daemon_state_android.cc(43)] Booted in dev mode.
启动过程中的日志打印并不多,不过在日志中可以通过这些日志来判断 update_engine 模块是否启动。
2.2.2 时序图
UpdateEngine 模块启动时序图如下:
2.2.3 启动流程分析
那接下来我们从上述的关键步骤出发,分析每一步骤的功能。
2.2.3.1 chromeos_update_engine::Terminator::Init()
代码路径:system/update_engine/common/terminator.cc
功能描述:这个方法通过 signal() 函数注册一个捕捉 SIGTERM 信号的功能,当程序触发 SIGTERM 信号时,会调用到 HandleSignal() 函数中执行,HandleSignal() 会调用 exit(1) 结束程序。
涉及知识:
A:SIGTERM 信号,信号是由操作系统传给进程的中断,会提早终止一个程序,有些信号不能被程序捕获,但下表中的信号可以在程序中捕获
信号 | 描述 |
---|---|
SIGABRT | 程序的异常终止,如调用 abort |
SIGFPE | 错误的算数运算,比如除以零或导致移除的操作 |
SIGILL | 检测非法指令 |
SIGINT | 程序终止(interrupt)信号 |
SIGSEGV | 非法访问内存 |
SIGTERM | 发送到程序的终止请求 |
B:exit(int)函数,exit() 为 C++ 的退出函数,功能为退出当前运行的程序,并将参数返回给主调进程。exit(0) 表示程序正常退出,非 0 表示非正常退出。
namespace chromeos_update_engine {
volatile sig_atomic_t Terminator::exit_status_ = 1; // default exit status
volatile sig_atomic_t Terminator::exit_blocked_ = 0;
volatile sig_atomic_t Terminator::exit_requested_ = 0;
void Terminator::Init() {
exit_blocked_ = 0;
exit_requested_ = 0;
signal(SIGTERM, HandleSignal);
}
void Terminator::Init(int exit_status) {
exit_status_ = exit_status;
Init();
}
void Terminator::Exit() {
exit(exit_status_);
}
void Terminator::HandleSignal(int signum) {
if (exit_blocked_ == 0) {
Exit();
}
exit_requested_ = 1;
}
ScopedTerminatorExitUnblocker::~ScopedTerminatorExitUnblocker() {
Terminator::set_exit_blocked(false);
if (Terminator::exit_requested()) {
Terminator::Exit();
}
}
2.2.3.2 brillo::FlagHelper::Init(argc, argv, “A/B Update Engine”)
代码路径:android/external/libbrillo/brillo/flag_helper.cc
说明:FlagHelper初始化的功能是初始化命令行相关的功能。
void FlagHelper::Init(int argc,
const char* const* argv,
std::string help_usage) {
brillo::FlagHelper* helper = GetInstance(); // 这里获取 FlagHelper 的单例
if (!helper->command_line_) {
if (!base::CommandLine::InitializedForCurrentProcess())
base::CommandLine::Init(argc, argv);
helper->command_line_ = base::CommandLine::ForCurrentProcess();
}
GetInstance()->SetUsageMessage(help_usage);
GetInstance()->UpdateFlagValues();
}
2.2.3.3 chromeos_update_engine::SetupLogging(log_to_system, log_to_file)
代码路径:android/system/update_engine/main.cc
功能说明:通过 LoggingSettings 模块将 update_engine 的日志存放到 /data/misc/update_engine_log 路径下
描述:在 update_engine.rc 里,启动项里是有带 --logtostderr --logtofile 参数的,所以当前的 log_to_system 和 log_to_file 都是 true。
void SetupLogging(bool log_to_system, bool log_to_file) {
logging::LoggingSettings log_settings;
log_settings.lock_log = logging::DONT_LOCK_LOG_FILE;
log_settings.logging_dest = static_cast<logging::LoggingDestination>(
(log_to_system ? logging::LOG_TO_SYSTEM_DEBUG_LOG : 0) |
(log_to_file ? logging::LOG_TO_FILE : 0));
log_settings.log_file = nullptr;
string log_file;
if (log_to_file) {
log_file = SetupLogFile(kSystemLogsRoot);
log_settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
log_settings.log_file = log_file.c_str();
}
/* logging::InitLogging(log_settings) 调用的并不是 Android 自带的 logger 机制里的方法,而是 libchrome 里的 logging,因为本身 update_engine 这个工程就是最早用于 chrome 里的,后面才移植到 Android 里来升级 AB 分区的,这里的 log 保存的文件路径 kSystemLogsRoot 为 “/data/misc/update_engine_log”。
*/
logging::InitLogging(log_settings);
// 在 InitLogging() 函数的系列调用中,最后通过 fopen 的方式打开 g_log_file_name,后面再通过追加写入的方式,去保存升级的 log。
#ifdef __ANDROID__
// The log file will have AID_LOG as group ID; this GID is inherited from the
// parent directory "/data/misc/update_engine_log" which sets the SGID bit.
chmod(log_file.c_str(), 0640);
#endif
}
2.2.3.4 xz_crc32_init()
功能说明:crc32 是用于数据校验的,xz_crc32()在没有硬件加速CRC指令的现代cpu上最快的版本是这个版本的3-5倍。
但是它们更大,使用更多的内存用于查找表。
2.2.3.5 umask(S_IRWXG | S_IRWXO)
什么是 umask:系统中的文件是有默认权限的,那么这个权限是怎么配置的呢?这就是 umask 的功能,umask 设置了用户创建文件的默认权限,它与 chmod 的效果刚好相反,umask 设置的是权限“补码”,而 chmod 设置的文件权限码。umask 命令是在 /etc/profile 文件中设置的,每个用户在登录时都会引用这个文件。
2.2.3.6 chromeos_update_engine::UpdateEngineDaemon update_engine_daemon && Run()
这里的内容就比较关键了,前面可见都没进行 update_engine 模块具体功能的配置,这里大有可能~
代码路径:android/system/update_engine/daemon.cc
Run() 函数实现在 daemon.cc 父类中,路径在 android/external/libbrillo/brillo/daemons/daemon.cc。
代码如下:
int Daemon::Run() {
int exit_code = OnInit();
if (exit_code != EX_OK)
return exit_code;
message_loop_.PostTask(
base::Bind(&Daemon::OnEventLoopStartedTask, base::Unretained(this)));
message_loop_.Run();
OnShutdown(&exit_code_);
// base::RunLoop::QuitClosure() causes the message loop to quit
// immediately, even if pending tasks are still queued.
// Run a secondary loop to make sure all those are processed.
// This becomes important when working with D-Bus since dbus::Bus does
// a bunch of clean-up tasks asynchronously when shutting down.
while (message_loop_.RunOnce(false /* may_block */)) {}
return exit_code_;
}
OnInit() 函数是从父类 daemon.cc 中的 Run() 函数调用过来的,路径在 android/system/update_engine/daemon.cc。是守护进程的初始化入口。
int UpdateEngineDaemon::OnInit() {
// Register the |subprocess_| singleton with this Daemon as the signal
// handler.
// 在这个守护进程中注册|subprocess_|单例作为信号处理程序。
subprocess_.Init(this);
// 回调到 父类Daemon 的 OnInit() 方法,注册当守护进程遇到 SIGTERM 和 SIGINT 时触发 Shutdown 流程;遇到 SIGHUP 信号时触发 Restart 流程
int exit_code = Daemon::OnInit();
if (exit_code != EX_OK)
return exit_code;
// true, Android.bp 中定义了 USE_BINDER = 1
#if USE_BINDER
// libbinderwrapper 路径:android/system/core/libbinderwrapper!
// Create() 函数在 binder_wrapper.cc 文件中,RealBinderWrapper 定义在 real_binder_wrapper.h 中
// BinderWrapper 是 Binder 的包装类,这里如果定义了 USE_BINDER,就初始化 Binder 服务的相关功能,以便后续注册 Binder 服务。
android::BinderWrapper::Create();
binder_watcher_.Init();
#endif // USE_BINDER
// false,Android.bp 中定义了 USE_OMAHA = 0
#if USE_OMAHA
// Initialize update engine global state but continue if something fails.
// TODO(deymo): Move the daemon_state_ initialization to a factory method
// avoiding the explicit re-usage of the |bus| instance, shared between
// D-Bus service and D-Bus client calls.
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.h 文件中
DaemonStateAndroid* daemon_state_android = new DaemonStateAndroid();
// daemon_state_ 是配置管理守护进程的状态,是 DaemonStateInterface 类对象,定义在 daemon_state_interface.h 文件中
// DaemonStateInterface 是父类,实际是 daemon_state_android 对象,定义在 daemon_state_android.h 中
daemon_state_.reset(daemon_state_android);
// 调用 daemon_state_android 的 Initialize() 函数
LOG_IF(ERROR, !daemon_state_android->Initialize())
<< "Failed to initialize system state.";
#endif // USE_OMAHA
// true,Android.bp 文件中定义的 USE_BINDER = 1
#if USE_BINDER
// Create the Binder Service. 创建 Binder 服务
// false 这里针对两套平台做了两个 Binder 服务
#if USE_OMAHA
binder_service_ = new BinderUpdateEngineBrilloService{real_system_state};
#else // !USE_OMAHA 进入此条件分支
// 将 daemon_state_android 的 service_delegate 对象配置为 binder 服务对象
binder_service_ = new BinderUpdateEngineAndroidService{
daemon_state_android->service_delegate()};
#endif // USE_OMAHA
// 获取 binder_wrapper 对象
auto binder_wrapper = android::BinderWrapper::Get();
// 调用 binder_wrapper 对象的 RegisterService() 方法将 binder 服务对象注册为 Binder 服务端
if (!binder_wrapper->RegisterService(binder_service_->ServiceName(),
binder_service_)) {
LOG(ERROR) << "Failed to register binder service.";
}
// 添加观察者,上层会注册 callback 对象到 daemon_state 对象中~后续会通过这里的 Observer 将信息回调到上层
daemon_state_->AddObserver(binder_service_.get());
#endif // USE_BINDER
// false,搜索后发现没有定义 USE_DBUS
#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 // !USE_DBUS 进入此条件分支
// 调用 StartUpdater() 开启服务
daemon_state_->StartUpdater();
#endif // USE_DBUS
return EX_OK;
}
OnInit() 函数就是守护进程的入口函数,线程集成 birllo::Daemon 守护进程类,子类实现父类方法 OnInit() 实现子类的功能初始化流程~
此处流程读下来,还是比较凌乱的,错综的功能关系,我们需要理清其中类对象以及对应的功能结构。在进行 Binder 服务注册的时候,会对于 OMAHA 系统有额外的 Binder 服务 RealSystemState 对象。而其他平台则为 DaemonStateAndroid 对象。
OK,让我们来重新将关于服务准备的关键流程整理出来
A:创建 DaemonStateAndroid 类,并调用其 Initialize() 方法
B:创建 BinderUpdateEngineAndroidService 类,构建 Binder 服务类以注册 Binder 服务
C:DaemonStateAndroid 添加 Observer 观察者,并开启服务初始化
2.2.3.6.1 DaemonStateAndroid
此类在 update_engine 守护进程的初始化过程中的关键角色,调用了其 Initialize()、AddObserver() 和 StartUpdater() 方法,此类继承了 DaemonStateInterface 类,并且定义了很多关键对象,链接升级的具体功能类,如下表所示:
变量 | 类 | 功能描述 |
---|---|---|
service_observers_ | set<ServiceObserverInterface*> | 定义回调函数的接口类 |
boot_control_ | BootControlInterface | 启动分区控制 |
hardware_ | HardwareInterface | 在Android平台上实现与硬件的真实接口 |
prefs_ | PrefsInterface | 属性管理 |
update_attempter_ | UpdateAttempterAndroid | 升级功能接口具体实现类,上层接口最终会调用到这里 |
openssl_wrapper_ | OpenSSLWrapper | OpenSSLWrapper和CertificateChecker用于检查SSL证书的更改。 |
certificate_checker_ | CertificateChecker | OpenSSLWrapper和CertificateChecker用于检查SSL证书的更改。 |
下面我们对 DaemonStateAndroid 中的方法进行解析
Initialize()
从流程上可以发现,Initialize() 中会对包含的 类对象 进行初始化。
bool DaemonStateAndroid::Initialize() {
// 初始化 BootControl,用于控制启动分区
boot_control_ = boot_control::CreateBootControl();
if (!boot_control_) {
LOG(WARNING) << "Unable to create BootControl instance, using stub "
<< "instead. All update attempts will fail.";
boot_control_.reset(new BootControlStub());
}
// 初始化 HardWare
hardware_ = hardware::CreateHardware();
if (!hardware_) {
LOG(ERROR) << "Error initializing the HardwareInterface.";
return false;
}
LOG_IF(INFO, !hardware_->IsNormalBootMode()) << "Booted in dev mode.";
LOG_IF(INFO, !hardware_->IsOfficialBuild()) << "Booted non-official build.";
// Initialize prefs. 初始化 Prefs,用于启动数据属性设置功能
base::FilePath non_volatile_path;
// TODO(deymo): Fall back to in-memory prefs if there's no physical directory
// available.
if (!hardware_->GetNonVolatileDirectory(&non_volatile_path)) {
LOG(ERROR) << "Failed to get a non-volatile directory.";
return false;
}
Prefs* prefs = new Prefs();
prefs_.reset(prefs);
if (!prefs->Init(non_volatile_path.Append(kPrefsSubDirectory))) {
LOG(ERROR) << "Failed to initialize preferences.";
return false;
}
// The CertificateChecker singleton is used by the update attempter. 获取初始化 CertificateChecker 单例
certificate_checker_.reset(
new CertificateChecker(prefs_.get(), &openssl_wrapper_));
certificate_checker_->Init();
// Initialize the UpdateAttempter before the UpdateManager.初始化 UpdateAttempterAndroid 对象
update_attempter_.reset(new UpdateAttempterAndroid(
this, prefs_.get(), boot_control_.get(), hardware_.get()));
return true;
}
AddObserver()
从流程中发现,AddObserver() 函数就是将 ServiceObserverInterface 对象插入到 service_observers 集合中。service_observers 是一个集合,其中存放的是 ServiceObserverInterface 类对象,类中定义了两个函数,用于向上层反馈升级状态/进度结果。ServiceObserverInterface 真正的实现者是 BinderUpdateEngineAndroidService 类,此类继承了 android::os::BnUpdateEngine 和 ServiceObserverInterface,所有来自上层的信息或反馈到上层的信息都会通过这里进行分发。
void DaemonStateAndroid::AddObserver(ServiceObserverInterface* observer) {
service_observers_.insert(observer);
}
class ServiceObserverInterface {
public:
virtual ~ServiceObserverInterface() = default;
// Called whenever the value of these parameters changes. For |progress|
// value changes, this method will be called only if it changes significantly.
virtual void SendStatusUpdate(
const update_engine::UpdateEngineStatus& update_engine_status) = 0;
// Called whenever an update attempt is completed.
virtual void SendPayloadApplicationComplete(ErrorCode error_code) = 0;
protected:
ServiceObserverInterface() = default;
};
StartUpdater()
bool DaemonStateAndroid::StartUpdater() {
// The DaemonState in Android is a passive daemon. It will only start applying
// an update when instructed to do so from the exposed binder API.
update_attempter_->Init();
return true;
}
函数会走到 UpdateAttempterAndroid 类的 Init() 方法,将升级功能类进行初始化
void UpdateAttempterAndroid::Init() {
// In case of update_engine restart without a reboot we need to restore the
// reboot needed state.
if (UpdateCompletedOnThisBoot()) {
SetStatusAndNotify(UpdateStatus::UPDATED_NEED_REBOOT);
} else {
SetStatusAndNotify(UpdateStatus::IDLE);
UpdatePrefsAndReportUpdateMetricsOnReboot();
}
}
// 初始化时会走到此函数中,其中使用 prefs 定义了初始属性
void UpdateAttempterAndroid::UpdatePrefsAndReportUpdateMetricsOnReboot() {
string current_boot_id;
TEST_AND_RETURN(utils::GetBootId(¤t_boot_id));
// Example: [ro.build.version.incremental]: [4292972]
string current_version =
android::base::GetProperty("ro.build.version.incremental", "");
TEST_AND_RETURN(!current_version.empty());
// If there's no record of previous version (e.g. due to a data wipe), we
// save the info of current boot and skip the metrics report.
if (!prefs_->Exists(kPrefsPreviousVersion)) {
prefs_->SetString(kPrefsBootId, current_boot_id);
prefs_->SetString(kPrefsPreviousVersion, current_version);
ClearMetricsPrefs();
return;
}
string previous_version;
// update_engine restarted under the same build.
// TODO(xunchang) identify and report rollback by checking UpdateMarker.
if (prefs_->GetString(kPrefsPreviousVersion, &previous_version) &&
previous_version == current_version) {
string last_boot_id;
bool is_reboot = prefs_->Exists(kPrefsBootId) &&
(prefs_->GetString(kPrefsBootId, &last_boot_id) &&
last_boot_id != current_boot_id);
// Increment the reboot number if |kPrefsNumReboots| exists. That pref is
// set when we start a new update.
if (is_reboot && prefs_->Exists(kPrefsNumReboots)) {
prefs_->SetString(kPrefsBootId, current_boot_id);
int64_t reboot_count =
metrics_utils::GetPersistedValue(kPrefsNumReboots, prefs_);
metrics_utils::SetNumReboots(reboot_count + 1, prefs_);
}
return;
}
// Now that the build version changes, report the update metrics.
// TODO(xunchang) check the build version is larger than the previous one.
prefs_->SetString(kPrefsBootId, current_boot_id);
prefs_->SetString(kPrefsPreviousVersion, current_version);
bool previous_attempt_exists = prefs_->Exists(kPrefsPayloadAttemptNumber);
// |kPrefsPayloadAttemptNumber| should be cleared upon successful update.
if (previous_attempt_exists) {
metrics_reporter_->ReportAbnormallyTerminatedUpdateAttemptMetrics();
}
metrics_utils::LoadAndReportTimeToReboot(
metrics_reporter_.get(), prefs_, clock_.get());
ClearMetricsPrefs();
// Also reset the update progress if the build version has changed.
if (!DeltaPerformer::ResetUpdateProgress(prefs_, false)) {
LOG(WARNING) << "Unable to reset the update progress.";
}
}
2.2.3.6.2 BinderUpdateEngineAndroidService
上面提到 BinderUpdateEngineAndroidService 是管理与上层交互的功能类,我们来看一下它的定义
class BinderUpdateEngineAndroidService : public android::os::BnUpdateEngine,
public ServiceObserverInterface {
public:
explicit BinderUpdateEngineAndroidService(
ServiceDelegateAndroidInterface* service_delegate);
~BinderUpdateEngineAndroidService() override = default;
const char* ServiceName() const { return "android.os.UpdateEngineService"; }
--------------------------------------------------------------------------------------------------------------------------------
// ServiceObserverInterface overrides.下面两个函数是来自 ServiceObserverInterface 类,封装了反馈信息给上层的接口
void SendStatusUpdate(
const update_engine::UpdateEngineStatus& update_engine_status) override;
void SendPayloadApplicationComplete(ErrorCode error_code) override;
--------------------------------------------------------------------------------------------------------------------------------
// android::os::BnUpdateEngine overrides.下面的函数是来自 android::os::BnUpdateEngine 类,HIDL类接口的实现。
android::binder::Status applyPayload(
const android::String16& url,
int64_t payload_offset,
int64_t payload_size,
const std::vector<android::String16>& header_kv_pairs) override;
android::binder::Status bind(
const android::sp<android::os::IUpdateEngineCallback>& callback,
bool* return_value) override;
android::binder::Status unbind(
const android::sp<android::os::IUpdateEngineCallback>& callback,
bool* return_value) override;
android::binder::Status suspend() override;
android::binder::Status resume() override;
android::binder::Status cancel() override;
android::binder::Status resetStatus() override;
android::binder::Status verifyPayloadApplicable(
const android::String16& metadata_filename, bool* return_value) override;
private:
// Remove the passed |callback| from the list of registered callbacks. Called
// on unbind() or whenever the callback object is destroyed.
// Returns true on success.
// 此函数作用是从注册回调列表中删除传递的回调对象,在上层调用 unbind() 或对象被销毁时调用
bool UnbindCallback(const IBinder* callback);
// List of currently bound callbacks. 回调对象列表,用于保存上层 bind() 传下来的回调对象
std::vector<android::sp<android::os::IUpdateEngineCallback>> callbacks_;
// Cached copy of the last status update sent. Used to send an initial
// notification when bind() is called from the client.
// 发送的最后一次状态更新的缓存副本。用于在从客户端调用 bind() 时发送初始通知。
int last_status_{-1};
double last_progress_{0.0};
// DaemonStateAndroid 类型实例,继承自 ServiceDelegateAndroidInterface,封装了 HIDI 接口,当上层调用 HIDL 接口时,会调用到
// DaemonStateAndroid 类中
ServiceDelegateAndroidInterface* service_delegate_;
};
从构造函数中,初始化 BinderUpdateEngineAndroidService 对象需要传入 ServiceDelegateAndroidInterface 实例,这个实例实际是 DaemonStateAndroid 对象。
2.2.3.6.3 binder_wrapper 注册 Binder 服务
注册 Binder 服务是通过 binder_wrapper->RegisterService(binder_service_->ServiceName(), binder_service_)) 调用,ServiceName() 返回的是注册服务端的服务名:“android.os.UpdateEngineService”。
2.2.3.7 chromeos_update_engine::Subprocess::Get().FlushBufferedLogsAtExit()
此函数是对于 update_engine 模块退出时触发的,更新 log 并退出。
2.2.4 启动流程总结
对于升级功能而言,相对重要的步骤是在 功能服务类的初始化以及服务的Binder注册 上。
1、守护进程 Daemon 的初始化及捕捉信号的处理逻辑注册;
2、获取 BinderWrapper 模块功能,并初始化对象,用以在 Binder 服务注册时提供接口功能;
3、实例化 DaemonStateAndroid 对象,这里会将升级过程中所需要的一系列功能对象初始化,如下:
变量 | 类 | 功能描述 |
---|---|---|
service_observers_ | set<ServiceObserverInterface*> | 定义回调函数的接口类 |
boot_control_ | BootControlInterface | 启动分区控制 |
hardware_ | HardwareInterface | 在Android平台上实现与硬件的真实接口 |
prefs_ | PrefsInterface | 属性管理,升级的很多状态,信息都是通过此模块配置/获取的 |
update_attempter_ | UpdateAttempterAndroid | 升级功能接口具体实现类,上层接口最终会调用到这里 |
openssl_wrapper_ | OpenSSLWrapper | OpenSSLWrapper和CertificateChecker用于检查SSL证书的更改。 |
certificate_checker_ | CertificateChecker | OpenSSLWrapper和CertificateChecker用于检查SSL证书的更改。 |
4、创建 BinderUpdateEngineAndroidService 对象,并注册为 android.os.UpdateEngineService Binder 服务;
5、调用 DaemonStateAndroid 的 AddObserver() 和 StartUpdater() 添加回调封装类,并开启升级功能;
dware_ | HardwareInterface | 在Android平台上实现与硬件的真实接口 |
| prefs_ | PrefsInterface | 属性管理,升级的很多状态,信息都是通过此模块配置/获取的 |
| update_attempter_ | UpdateAttempterAndroid | 升级功能接口具体实现类,上层接口最终会调用到这里 |
| openssl_wrapper_ | OpenSSLWrapper | OpenSSLWrapper和CertificateChecker用于检查SSL证书的更改。 |
| certificate_checker_ | CertificateChecker | OpenSSLWrapper和CertificateChecker用于检查SSL证书的更改。 |
4、创建 BinderUpdateEngineAndroidService 对象,并注册为 android.os.UpdateEngineService Binder 服务;
5、调用 DaemonStateAndroid 的 AddObserver() 和 StartUpdater() 添加回调封装类,并开启升级功能;