Android P update_engine分析 -- update_engine_daemon的启动

Posted Give.Me.Five

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android P update_engine分析 -- update_engine_daemon的启动相关的知识,希望对你有一定的参考价值。

上篇我们在update_engine启动时,分析了update_engine日志logging的启动和log文件的操作。这篇我们继续来研究update_engine_daemon的启动过程。因为updateEngineDaemon是继承brillo::Daemon的。从Daemon.Run()可以看到会调用onInit()函数。

int UpdateEngineDaemon::OnInit() 
  subprocess_.Init(this);
  //父类初始化
  int exit_code = Daemon::OnInit();
  //Binder初始化
  android::BinderWrapper::Create();
  binder_watcher_.Init();
  //DaemonStateAndroid的初始化
  DaemonStateAndroid* daemon_state_android = new DaemonStateAndroid();
  daemon_state_.reset(daemon_state_android);
  LOG_IF(ERROR, !daemon_state_android->Initialize())
      << "Failed to initialize system state.";
  //初始化BinderUpdateEngineAndroidService
  binder_service_ = new BinderUpdateEngineAndroidService
      daemon_state_android->service_delegate();
  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());
  //启动updater   
  daemon_state_->StartUpdater();  

updateEngineDaemon的onInit()里大致做了三件事情:1. 初始化DaemonStateAndroid 2. 初始化BinderUpdateEngineAndroidService 3.启动startUpdater.

初始化DaemonStateAndroid

bool DaemonStateAndroid::Initialize() 
  //初始化boot_control
  boot_control_ = boot_control::CreateBootControl();
  //创建硬件相关接口,主要以属性操作为主
  hardware_ = hardware::CreateHardware();
  //初始化存取key的存储接口
  Prefs* prefs = new Prefs();
  prefs_.reset(prefs);
  if (!prefs->Init(non_volatile_path.Append(kPrefsSubDirectory))) 
    LOG(ERROR) << "Failed to initialize preferences.";
    return false;
   
  //校验类的初始化
  certificate_checker_.reset(
    new CertificateChecker(prefs_.get(), &openssl_wrapper_));
  certificate_checker_->Init();
  //update_attempter的实始化
  update_attempter_.reset(new UpdateAttempterAndroid(
      this, prefs_.get(), boot_control_.get(), hardware_.get()));

DaemonStateAndroid的初始化主要做了如下事件

  1. boot_control的初始化,为后面的切换A/B slot做准备。后续专门写一篇来详细说明
  2. hardware的初始化,为了后续获取版本信息,OOB的状态,编译时间等信息
  3. prefs的初始化,主要为了从文件中读写key
  4. certificateChecker的初始化,主要为后面验证升级包
  5. updateAttempterAndroid的初始化, 基于前面获取的boot_control, perfs, hardware的实类初始化

初始化BinderUpdateEngineAndroidService

BinderUpdateEngineAndroidService::BinderUpdateEngineAndroidService(
    ServiceDelegateAndroidInterface* service_delegate)
    : service_delegate_(service_delegate) 

从上面代码看,初始化BinderUpdateEngineAndroidService时,会把DaemonStateAndroid 的实例指针传给BinderUpdateEngineAndroidService。然后DaemonStateAndroid 会调用 AddObserver,将这个加入到service_observers_的列表中,后续通过调用service_observers()来获取这个列表,从而获取这个函数指针来调用其函数。其函数列表里有:

  // android::os::BnUpdateEngine overrides.
  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;

启动startUpdater

bool DaemonStateAndroid::StartUpdater() 
  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();
  

bool UpdateAttempterAndroid::UpdateCompletedOnThisBoot() 
  // In case of an update_engine restart without a reboot, we stored the boot_id
  // when the update was completed by setting a pref, so we can check whether
  // the last update was on this boot or a previous one.
  string boot_id;
  TEST_AND_RETURN_FALSE(utils::GetBootId(&boot_id));

  string update_completed_on_boot_id;
  //判断配置升级完成的bootid 与当前的bootId,是不是同一个???
  return (prefs_->Exists(kPrefsUpdateCompletedOnBootId) &&
          prefs_->GetString(kPrefsUpdateCompletedOnBootId,
                            &update_completed_on_boot_id) &&
          update_completed_on_boot_id == boot_id);

void UpdateAttempterAndroid::SetStatusAndNotify(UpdateStatus status) 
  status_ = status;
  size_t payload_size =
      install_plan_.payloads.empty() ? 0 : install_plan_.payloads[0].size;
  UpdateEngineStatus status_to_send = .status = status_,
                                       .progress = download_progress_,
                                       .new_size_bytes = payload_size;
//遍历所有监控者
  for (auto observer : daemon_state_->service_observers()) 
  	//将当前状态通知监控者
    observer->SendStatusUpdate(status_to_send);
  
  last_notify_time_ = TimeTicks::Now();

上面注释与逻辑中可以看到,我们需要先去看当前的bootid 是否需要等待重启切换slot, 如果需要刚通知上面的调用方去上报状态。不需要重启,也需要上报空闲状态,同时更新perfs配置。下面来看如何更新配置:


void UpdateAttempterAndroid::UpdatePrefsAndReportUpdateMetricsOnReboot() 
  string current_boot_id;
  //获取当前slot
  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;
  // 更新bootid 和 重启次数
  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;
  
  // 更新bootid
  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();


到这里update_engine_daemon的启动信息就升级完了

以上是关于Android P update_engine分析 -- update_engine_daemon的启动的主要内容,如果未能解决你的问题,请参考以下文章

Android P 显示流程分析---界面刷新

Android P 显示流程分析---EventThread MessageQueue 交互分析

Android P 显示流程---Display设备初始化过程分析

Android P 显示流程分析--- buffer的生产消费者模式

Android P 显示流程分析--- buffer的生产消费者模式

Android P update_engine分析-- PostinstallRunnerAction的工作