update_engine簡介
update_engine是A/B升級的核心邏輯。理解了update_engine就理解了在Android系統中A/B升級是如何運行的。它的代碼放在源碼目錄下system/update_engine/下。那麼接下來對update_engine進行分析,首先會分析它的結構,以後分析它的核心操做。android
update_engine結構分析
Android.mk分析
一個源碼工程中包含的源文件會有不少,可是不表明全部的文件都和咱們的目標相關。而經過Android.mk文件能夠找到和分析目標update_engine相關的源文件。咱們只須要關注這些文件即可。Android.mk中直接和update_engine相關的內容chrome
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中。接下來再看它必定依賴的文件。app
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。因此該模塊還依賴以下curl
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來肯定咱們所須要的文件。async
從main.cc開始分析
src/system/update_engine/main.ccide
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.hoop
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類的內容了:ui
src/external/librillo/brillo/daemons/daemon.ccthis
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()。