Android UpdateEngine 模块分析(二)UpdateEngine 服务启动

前言

前一章节分析了 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_OpenSSLWrapperOpenSSLWrapper和CertificateChecker用于检查SSL证书的更改。
certificate_checker_CertificateCheckerOpenSSLWrapper和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(&current_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_OpenSSLWrapperOpenSSLWrapper和CertificateChecker用于检查SSL证书的更改。
certificate_checker_CertificateCheckerOpenSSLWrapper和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() 添加回调封装类,并开启升级功能;

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

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值