update_engine-整体结构(一)


update_engine简介

update_engine是A/B升级的核心逻辑。理解了update_engine就理解了在Android系统中A/B升级是如何运行的。它的代码放在源码目录下system/update_engine/下。那么接下来对update_engine进行分析,首先会分析它的结构,之后分析它的核心操作。

update_engine结构分析

Android.mk分析

一个源码工程中包含的源文件会有很多,但是不代表所有的文件都和我们的目标相关。而通过Android.mk文件可以找到和分析目标update_engine相关的源文件。我们只需要关注这些文件便可。Android.mk中直接和update_engine相关的内容

 1 include $(CLEAR_VARS)  2 LOCAL_MODULE := update_engine  3 LOCAL_MODULE_CLASS := EXECUTABLES  4 LOCAL_REQUIRED_MODULES := \  5  cacerts_google  6 LOCAL_CPP_EXTENSION := .cc  7 LOCAL_CLANG := true
 8 LOCAL_CFLAGS := $(ue_common_cflags)  9 LOCAL_CPPFLAGS := $(ue_common_cppflags) 10 LOCAL_LDFLAGS := $(ue_common_ldflags) 11 LOCAL_C_INCLUDES := \ 12  $(ue_common_c_includes) 13 LOCAL_SHARED_LIBRARIES := \ 14  $(ue_common_shared_libraries) 15 LOCAL_STATIC_LIBRARIES := \ 16  $(ue_common_static_libraries) 17 LOCAL_SRC_FILES := \ 18  main.cc 19 
20 ifeq ($(local_use_omaha),1) 21 LOCAL_C_INCLUDES += \ 22  $(ue_libupdate_engine_exported_c_includes) 23 LOCAL_STATIC_LIBRARIES += \ 24  libupdate_engine \ 25     $(ue_libupdate_engine_exported_static_libraries:-host=) 26 LOCAL_SHARED_LIBRARIES += \ 27     $(ue_libupdate_engine_exported_shared_libraries:-host=) 28 else  # local_use_omaha == 1
29 LOCAL_STATIC_LIBRARIES += \ 30  libupdate_engine_android \ 31     $(ue_libupdate_engine_android_exported_static_libraries:-host=) 32 LOCAL_SHARED_LIBRARIES += \ 33     $(ue_libupdate_engine_android_exported_shared_libraries:-host=) 34 endif  # local_use_omaha == 1
35 
36 LOCAL_INIT_RC := update_engine.rc 37 include $(BUILD_EXECUTABLE)

 从中首先可以获取到的信息就是该模块是个可执行的模块,并且入口函数在main.cc中。接下来再看它一定依赖的文件。

 1 ue_common_c_includes := \ #依赖的c文件  2     $(LOCAL_PATH)/client_library/include \  3  system  4 
 5 ue_common_shared_libraries := \ #依赖的动态库  6     libbrillo-stream \  7  libbrillo \ #在源码下的external中  8  libchrome #在源码下的external中  9 
10 ue_common_static_libraries := \ #依赖的静态库 11     libgtest_prod \             

由于local_use_omaha := $(if $(filter true,$(PRODUCT_IOT)),1,0) 意思为该设备是否是IOT设备,如果是则值为1否则为0,在这里我们分析的状况是非IOT设备。所以local_use_omaha := 0。所以该模块还依赖如下

 1 LOCAL_STATIC_LIBRARIES += \ #静态依赖  2  libupdate_engine_android \  3     $(ue_libupdate_engine_android_exported_static_libraries:-host=)  4 -------------------------------------------------------------------------
 5 ue_libupdate_engine_android_exported_static_libraries := \  6  libpayload_consumer \  7  libfs_mgr \  8  libbase \  9  liblog \ 10  $(ue_libpayload_consumer_exported_static_libraries) \ 11  libupdate_engine_boot_control \ 12  $(ue_libupdate_engine_boot_control_exported_static_libraries) 13     ue_libupdate_engine_android_exported_shared_libraries := \ 14  $(ue_libpayload_consumer_exported_shared_libraries) \ 15  $(ue_libupdate_engine_boot_control_exported_shared_libraries) \ 16  libandroid_net \ 17  libbinder \ 18  libbinderwrapper \ 19     libbrillo-binder \ 20  libcutils \ 21  libcurl \ 22  libssl \ 23  libutils 24 
25 LOCAL_SHARED_LIBRARIES += \ #动态依赖 26     $(ue_libupdate_engine_android_exported_shared_libraries:-host=) 27 -------------------------------------------------------------------------
28 ue_libupdate_engine_android_exported_shared_libraries := \ 29  $(ue_libpayload_consumer_exported_shared_libraries) \ 30  $(ue_libupdate_engine_boot_control_exported_shared_libraries) \ 31  libandroid_net \ 32  libbinder \ 33  libbinderwrapper \ 34     libbrillo-binder \ 35  libcutils \ 36  libcurl \ 37  libssl \ 38     libutils

可以看到其中还有很多依赖的源文件是以变量赋值的形式出现的。这里就不一一列出了,但是方法已经知道了,那就是当遇到一个方法存在于两个文件中时就可以通过Android.mk来确定我们所需要的文件。

从main.cc开始分析

src/system/update_engine/main.cc

 1 int main(int argc, char** argv) {  2   DEFINE_bool(logtostderr, false,  3               "Write logs to stderr instead of to a file in log_dir.");  4   DEFINE_bool(foreground, false,  5               "Don't daemon()ize; run in foreground.");  6 
 7  chromeos_update_engine::Terminator::Init();  8   brillo::FlagHelper::Init(argc, argv, "Chromium OS Update Engine");  9  chromeos_update_engine::SetupLogging(FLAGS_logtostderr); 10   if (!FLAGS_foreground) 11     PLOG_IF(FATAL, daemon(0, 0) == 1) << "daemon() failed"; 12 
13   LOG(INFO) << "Chrome OS Update Engine starting"; 14 
15   // xz-embedded requires to initialize its CRC-32 table once on startup.
16  xz_crc32_init(); 17 
18   // Ensure that all written files have safe permissions. 19   // This is a mask, so we _block_ all permissions for the group owner and other 20   // users but allow all permissions for the user owner. We allow execution 21   // for the owner so we can create directories. 22   // Done _after_ log file creation.
23   umask(S_IRWXG | S_IRWXO); 24 
25  chromeos_update_engine::UpdateEngineDaemon update_engine_daemon; 26   int exit_code = update_engine_daemon.Run(); 27 
28   LOG(INFO) << "Chrome OS Update Engine terminating with exit code "
29             << exit_code; 30   return exit_code; 31 }

可以看到首先进行了初始化工作,这些初始化并不影响对程序主干的分析,所以可以暂时略过。直接看最重要的UpdateEngineDaemon以及其Run()方法。UpdateEngineDaemon继承了brillo::Daemon,UpdateEngineDaemon的内容为

src/system/update_engine/daemon.h

 1 namespace chromeos_update_engine {  2 
 3 class UpdateEngineDaemon : public brillo::Daemon {  4  public:  5   UpdateEngineDaemon() = default;  6 
 7  protected:  8   int OnInit() override;  9 
10  private: 11 #if USE_DBUS
12   // Run from the main loop when the |dbus_adaptor_| object is registered. At 13   // this point we can request ownership of the DBus service name and continue 14   // initialization.
15   void OnDBusRegistered(bool succeeded); 16 
17   // Main D-Bus service adaptor.
18   std::unique_ptr<UpdateEngineAdaptor> dbus_adaptor_; 19 #endif  // USE_DBUS
20 
21   // The Subprocess singleton class requires a brillo::MessageLoop in the 22   // current thread, so we need to initialize it from this class instead of 23   // the main() function.
24  Subprocess subprocess_; 25 
26 #if USE_BINDER
27  brillo::BinderWatcher binder_watcher_; 28 #endif  // USE_BINDER
29 
30 #if USE_BINDER
31 #if USE_OMAHA
32   android::sp<BinderUpdateEngineBrilloService> binder_service_; 33 #else  // !USE_OMAHA
34   android::sp<BinderUpdateEngineAndroidService> binder_service_; 35 #endif  // USE_OMAHA
36 #endif  // USE_BINDER
37 
38   // The daemon state with all the required daemon classes for the configured 39   // platform.
40   std::unique_ptr<DaemonStateInterface> daemon_state_; 41 
42  DISALLOW_COPY_AND_ASSIGN(UpdateEngineDaemon); 43 }; 44 
45 }  // namespace chromeos_update_engine
46 
47 #endif  // UPDATE_ENGINE_DAEMON_H_

从中可以看到它并没有对Run()进行重写,所以必须要看看daemon类的内容了:

src/external/librillo/brillo/daemons/daemon.cc

 1 namespace brillo {  2  ........  3 int Daemon::Run() {  4   int exit_code = OnInit();              //会调用子类的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   while (message_loop_.RunOnce(false /* may_block */)) {} 18 
19   return exit_code_; 20 } 21 
22 int Daemon::OnInit() { 23  async_signal_handler_.Init(); 24   for (int signal : {SIGTERM, SIGINT}) { 25  async_signal_handler_.RegisterHandler( 26         signal, base::Bind(&Daemon::Shutdown, base::Unretained(this))); 27  } 28  async_signal_handler_.RegisterHandler( 29       SIGHUP, base::Bind(&Daemon::Restart, base::Unretained(this))); 30   return EX_OK; 31 } 32  ........ 33 } 

 可以看到在Run()方法中主要就是调用了OnInit()方法,子类一旦对其进行了重写那么就会调用子类的OnInit()方法.UpdateEngineDaemon的Oninit()方法体如下:

src/system/update_engine/daemon.cc

 1 namespace chromeos_update_engine {  2 
 3 int UpdateEngineDaemon::OnInit() {  4   // Register the |subprocess_| singleton with this Daemon as the signal  5   // handler.
 6   subprocess_.Init(this);                      //初始化子进程,用来处理信号
 7 
 8   int exit_code = Daemon::OnInit();             //调用父类的OnInit()方法
 9   if (exit_code != EX_OK) 10     return exit_code; 11 
12 #if USE_BINDER                                   //USE_BINDER=1 
13   android::BinderWrapper::Create();             //创建BinderWrapper
14  binder_watcher_.Init(); 15 #endif  // USE_BINDER
16 
17 #if USE_OMAHA                                  //USE_OMAHA=0
18   // Initialize update engine global state but continue if something fails. 19   // TODO(deymo): Move the daemon_state_ initialization to a factory method 20   // avoiding the explicit re-usage of the |bus| instance, shared between 21   // D-Bus service and D-Bus client calls.
22   RealSystemState* real_system_state = new RealSystemState(); 23  daemon_state_.reset(real_system_state); 24   LOG_IF(ERROR, !real_system_state->Initialize()) 25       << "Failed to initialize system state."; 26 #else  // !USE_OMAHA
27   DaemonStateAndroid* daemon_state_android = new DaemonStateAndroid(); 28  daemon_state_.reset(daemon_state_android); 29   LOG_IF(ERROR, !daemon_state_android->Initialize()) 30       << "Failed to initialize system state."; 31 #endif  // USE_OMAHA
32 
33 #if USE_BINDER
34   // Create the Binder Service.
35 #if USE_OMAHA
36   binder_service_ = new BinderUpdateEngineBrilloService{real_system_state}; 37 #else  // !USE_OMAHA
38   binder_service_ = new BinderUpdateEngineAndroidService{ 39       daemon_state_android->service_delegate()};             //创建binder_service
40 #endif  // USE_OMAHA
41   auto binder_wrapper = android::BinderWrapper::Get(); 42   if (!binder_wrapper->RegisterService(binder_service_->ServiceName(),    //向ServiceManager注册binder_service
43  binder_service_)) { 44     LOG(ERROR) << "Failed to register binder service."; 45  } 46 
47   daemon_state_->AddObserver(binder_service_.get());                      //将binder_service添加到观察者队列中
48 #endif  // USE_BINDER
49 
50 #if USE_DBUS                                                              //USE_DBUS=0
51   // Create the DBus service.
52   dbus_adaptor_.reset(new UpdateEngineAdaptor(real_system_state)); 53   daemon_state_->AddObserver(dbus_adaptor_.get()); 54 
55   dbus_adaptor_->RegisterAsync(base::Bind(&UpdateEngineDaemon::OnDBusRegistered, 56                                           base::Unretained(this))); 57   LOG(INFO) << "Waiting for DBus object to be registered."; 58 #else  // !USE_DBUS
59   daemon_state_->StartUpdater();                                          //开始服务的核心流程
60 #endif  // USE_DBUS
61   return EX_OK; 62 }

在Oninit()中其实主要就是做了两件事,首先是对Binder进行了初始化,包括创建,注册,添加到观察者队列中。其次就是创建了DaemonStateAndroid,并将其赋给daemon_state_,最后调用daemon_state_->StartUpdater()。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM