1. 程式人生 > >Android OTA升級原理和流程分析(一)

Android OTA升級原理和流程分析(一)

這篇及以後的篇幅將通過分析update.zip包在具體Android系統升級的過程,來理解Android系統中Recovery模式服務的工作原理。我們先從update.zip包的製作開始,然後是Android系統的啟動模式分析,Recovery工作原理,如何從我們上層開始選擇system update到重啟到Recovery服務,以及在Recovery服務中具體怎樣處理update.zip包升級的,我們的安裝指令碼updater-script怎樣被解析並執行的等一系列問題。分析過程中所用的Android原始碼是gingerbread0919(tcc88xx開發板標配的),測試開發板是tcc88xx。這是在工作中總結的文件,當然在網上參考了不少內容,如有雷同純屬巧合吧,在分析過程中也存在很多未解決的問題,也希望大家不吝指教。

一、 update.zip包的目錄結構
          |----boot.img
          |----system/
          |----recovery/
                `|----recovery-from-boot.p
                `|----etc/
                        `|----install-recovery.sh
          |---META-INF/
              `|CERT.RSA
              `|CERT.SF
              `|MANIFEST.MF

              `|----com/
                     `|----google/
                             `|----android/
                                    `|----update-binary
                                    `|----updater-script
                             `|----android/
                                    `|----metadata

二、 update.zip包目錄結構詳解
         以上是我們用命令make otapackage 製作的update.zip包的標準目錄結構。
1、boot.img是更新boot分割槽所需要的檔案。這個boot.img主要包括kernel+ramdisk。

         2、system/目錄的內容在升級後會放在系統的system分割槽。主要用來更新系統的一些應用或則應用會用到的一些庫等等。可以將Android原始碼編譯out/target/product/tcc8800/system/中的所有檔案拷貝到這個目錄來代替。

3、recovery/目錄中的recovery-from-boot.p是boot.img和recovery.img的補丁(patch),主要用來更新recovery分割槽,其中etc/目錄下的install-recovery.sh是更新指令碼。
4、update-binary是一個二進位制檔案,相當於一個指令碼直譯器,能夠識別updater-script中描述的操作。該檔案在Android原始碼編譯後out/target/product/tcc8800/system bin/updater生成,可將updater重新命名為update-binary得到。
               該檔案在具體的更新包中的名字由原始碼中bootable/recovery/install.c中的巨集ASSUMED_UPDATE_BINARY_NAME的值而定。
5、updater-script:此檔案是一個指令碼檔案,具體描述了更新過程。我們可以根據具體情況編寫該指令碼來適應我們的具體需求。該檔案的命名由原始碼中bootable/recovery/updater/updater.c檔案中的巨集SCRIPT_NAME的值而定。
6、 metadata檔案是描述裝置資訊及環境變數的元資料。主要包括一些編譯選項,簽名公鑰,時間戳以及裝置型號等。
7、我們還可以在包中新增userdata目錄,來更新系統中的使用者資料部分。這部分內容在更新後會存放在系統的/data目錄下。

         8、update.zip包的簽名:update.zip更新包在製作完成後需要對其簽名,否則在升級時會出現認證失敗的錯誤提示。而且簽名要使用和目標板一致的加密公鑰。加密公鑰及加密需要的三個檔案在Android原始碼編譯後生成的具體路徑為:

               out/host/linux-x86/framework/signapk.jar 

               build/target/product/security/testkey.x509.pem         

               build/target/product/security/testkey.pk8 。

              我們用命令make otapackage製作生成的update.zip包是已簽過名的,如果自己做update.zip包時必須手動對其簽名。

              具體的加密方法:$ java –jar gingerbread/out/host/linux/framework/signapk.jar –w gingerbread/build/target/product/security/testkey.x509.pem                                      gingerbread/build/target/product/security/testkey.pk8 update.zip update_signed.zip
              以上命令在update.zip包所在的路徑下執行,其中signapk.jar testkey.x509.pem以及testkey.pk8檔案的引用使用絕對路徑。update.zip 是我們已經打好的包,update_signed.zip包是命令執行完生成的已經簽過名的包。
9、MANIFEST.MF:這個manifest檔案定義了與包的組成結構相關的資料。類似Android應用的mainfest.xml檔案。
10、CERT.RSA:與簽名檔案相關聯的簽名程式塊檔案,它儲存了用於簽名JAR檔案的公共簽名。
11、CERT.SF:這是JAR檔案的簽名檔案,其中字首CERT代表簽名者。
        另外,在具體升級時,對update.zip包檢查時大致會分三步:①檢驗SF檔案與RSA檔案是否匹配。②檢驗MANIFEST.MF與簽名檔案中的digest是否一致。③檢驗包中的檔案與MANIFEST中所描述的是否一致。
三、 Android升級包update.zip的生成過程分析

         1) 對於update.zip包的製作有兩種方式,即手動製作和命令生成。

          第一種手動製作:即按照update.zip的目錄結構手動建立我們需要的目錄。然後將對應的檔案拷貝到相應的目錄下,比如我們向系統中新加一個應用程式。可以將新增的應用拷貝到我們新建的update/system/app/下(system目錄是事先拷貝編譯原始碼後生成的system目錄),打包並簽名後,拷貝到SD卡就可以使用了。這種方式在實際的tcc8800開發板中未測試成功。簽名部分未通過,可能與具體的開發板相關。

          第二種製作方式:命令製作。Android原始碼系統中為我們提供了製作update.zip刷機包的命令,即make otapackage。該命令在編譯原始碼完成後並在原始碼根目錄下執行。 具體操作方式:在原始碼根目錄下執行

                ①$ . build/envsetup.sh。 

                ②$ lunch 然後選擇你需要的配置(如17)。

                ③$ make otapackage。

          在編譯完原始碼後最好再執行一遍上面的①、②步防止執行③時出現未找到對應規則的錯誤提示。命令執行完成後生成的升級包所在位置在out/target/product/full_tcc8800_evm_target_files-eng.mumu.20120309.111059.zip將這個包重新命名為update.zip,並拷貝到SD卡中即可使用。

           這種方式(即完全升級)在tcc8800開發板中已測試成功。

       2) 使用make otapackage命令生成update.zip的過程分析。
            在原始碼根目錄下執行make otapackage命令生成update.zip包主要分為兩步,第一步是根據Makefile執行編譯生成一個update原包(zip格式)。第二步是執行一個python指令碼,並以上一步準備的zip包作為輸入,最終生成我們需要的升級包。下面進一步分析這兩個過程。

            第一步:編譯Makefile。對應的Makefile檔案所在位置:build/core/Makefile。從該檔案的884行(tcc8800,gingerbread0919)開始會生成一個zip包,這個包最後會用來製作OTA package 或者filesystem image。先將這部分的對應的Makefile貼出來如下:

  1. # -----------------------------------------------------------------  
  2. # A zip of the directories that map to the target filesystem.  
  3. # This zip can be used to create an OTA package or filesystem image  
  4. # as a post-build step.  
  5. #  
  6. name := $(TARGET_PRODUCT)  
  7. ifeq ($(TARGET_BUILD_TYPE),debug)  
  8.   name := $(name)_debug  
  9. endif  
  10. name := $(name)-target_files-$(FILE_NAME_TAG)  
  11. intermediates := $(call intermediates-dir-for,PACKAGING,target_files)  
  12. BUILT_TARGET_FILES_PACKAGE := $(intermediates)/$(name).zip  
  13. $(BUILT_TARGET_FILES_PACKAGE): intermediates := $(intermediates)  
  14. $(BUILT_TARGET_FILES_PACKAGE): \  
  15.         zip_root := $(intermediates)/$(name)  
  16. # $(1): Directory to copy  
  17. # $(2): Location to copy it to  
  18. # The "ls -A" is to prevent "acp s/* d" from failing if s is empty.  
  19. define package_files-copy-root  
  20.   if [ -d "$(strip $(1))" -a "$$(ls -A $(1))" ]; then \  
  21.     mkdir -p $(2) && \  
  22.     $(ACP) -rd $(strip $(1))/* $(2); \  
  23.   fi  
  24. endef  
  25. built_ota_tools := \  
  26.     $(call intermediates-dir-for,EXECUTABLES,applypatch)/applypatch \  
  27.     $(call intermediates-dir-for,EXECUTABLES,applypatch_static)/applypatch_static \  
  28.     $(call intermediates-dir-for,EXECUTABLES,check_prereq)/check_prereq \  
  29.     $(call intermediates-dir-for,EXECUTABLES,updater)/updater  
  30. $(BUILT_TARGET_FILES_PACKAGE): PRIVATE_OTA_TOOLS := $(built_ota_tools)  
  31. $(BUILT_TARGET_FILES_PACKAGE): PRIVATE_RECOVERY_API_VERSION := $(RECOVERY_API_VERSION)  
  32. ifeq ($(TARGET_RELEASETOOLS_EXTENSIONS),)  
  33. # default to common dir for device vendor  
  34. $(BUILT_TARGET_FILES_PACKAGE): tool_extensions := $(TARGET_DEVICE_DIR)/../common  
  35. else  
  36. $(BUILT_TARGET_FILES_PACKAGE): tool_extensions := $(TARGET_RELEASETOOLS_EXTENSIONS)  
  37. endif  
  38. # Depending on the various images guarantees that the underlying  
  39. # directories are up-to-date.  
  40. $(BUILT_TARGET_FILES_PACKAGE): \  
  41.         $(INSTALLED_BOOTIMAGE_TARGET) \  
  42.         $(INSTALLED_RADIOIMAGE_TARGET) \  
  43.         $(INSTALLED_RECOVERYIMAGE_TARGET) \  
  44.         $(INSTALLED_SYSTEMIMAGE) \  
  45.         $(INSTALLED_USERDATAIMAGE_TARGET) \  
  46.         $(INSTALLED_ANDROID_INFO_TXT_TARGET) \  
  47.         $(built_ota_tools) \  
  48.         $(APKCERTS_FILE) \  
  49.         $(HOST_OUT_EXECUTABLES)/fs_config \  
  50.         | $(ACP)  
  51.     @echo "Package target files: [email protected]"  
  52.     $(hide) rm -rf [email protected] $(zip_root)  
  53.     $(hide) mkdir -p $(dir [email protected]) $(zip_root)  
  54.     @# Components of the recovery image  
  55.     $(hide) mkdir -p $(zip_root)/RECOVERY  
  56.     $(hide) $(call package_files-copy-root, \  
  57.         $(TARGET_RECOVERY_ROOT_OUT),$(zip_root)/RECOVERY/RAMDISK)  
  58. ifdef INSTALLED_KERNEL_TARGET  
  59.     $(hide) $(ACP) $(INSTALLED_KERNEL_TARGET) $(zip_root)/RECOVERY/kernel  
  60. endif  
  61. ifdef INSTALLED_2NDBOOTLOADER_TARGET  
  62.     $(hide) $(ACP) \  
  63.         $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/RECOVERY/second  
  64. endif  
  65. ifdef BOARD_KERNEL_CMDLINE  
  66.     $(hide) echo "$(BOARD_KERNEL_CMDLINE)" > $(zip_root)/RECOVERY/cmdline  
  67. endif  
  68. ifdef BOARD_KERNEL_BASE  
  69.     $(hide) echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/RECOVERY/base  
  70. endif  
  71. ifdef BOARD_KERNEL_PAGESIZE  
  72.     $(hide) echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/RECOVERY/pagesize  
  73. endif  
  74.     @# Components of the boot image  
  75.     $(hide) mkdir -p $(zip_root)/BOOT  
  76.     $(hide) $(call package_files-copy-root, \  
  77.         $(TARGET_ROOT_OUT),$(zip_root)/BOOT/RAMDISK)  
  78. ifdef INSTALLED_KERNEL_TARGET  
  79.     $(hide) $(ACP) $(INSTALLED_KERNEL_TARGET) $(zip_root)/BOOT/kernel  
  80. endif  
  81. ifdef INSTALLED_2NDBOOTLOADER_TARGET  
  82. 相關推薦

    Android OTA升級原理流程分析

    這篇及以後的篇幅將通過分析update.zip包在具體Android系統升級的過程,來理解Android系統中Recovery模式服務的工作原理。我們先從update.zip包的製作開始,然後是Android系統的啟動模式分析,Recovery工作原理,如何從

    Android OTA升級原理流程分析---Android系統的三種啟動模式

            以下的篇幅開始分析我們在上兩個篇幅中生成的update.zip包在具體更新中所經過的過程,並根據原始碼分析每一部分的工作原理。 一、       系統更新update.zip包的兩種方式 1.  通過上一個文件,我們知道了怎樣製作一個updat

    Android OTA升級原理流程分析---update.zip差分包問題的解決

    Android OTA升級原理和流程分析(二)—update.zip差分包問題的解決 在上一篇末尾提到的生成差分包時出現的問題,現已解決,由於最近比較忙,相隔的時間也比較長,所以單列一個篇幅提示大家。這個問題居然是原始碼中的問題,可能你已經制作成功了,不過我的

    Android系統載入Apk檔案的時機流程分析1--Android 4.4.4 r1的原始碼

    Android系統在啟動時安裝應用程式的過程,這些應用程式安裝好之後,還需要有一個Home應用程式來負責把它們在桌面上展示出來,在Android系統中,這個預設的Home應用程式就是Launcher了。Android系統的Home應用程式Launcher是由Activit

    Java多執行緒之AQSAbstractQueuedSynchronizer 實現原理原始碼分析

    章節概覽、 1、回顧 上一章節,我們分析了ReentrantLock的原始碼: 2、AQS 佇列同步器概述 本章節我們深入分析下AQS(AbstractQueuedSynchronizer)佇列同步器原始碼,AQS是用來構建鎖或者其他同步元件的基礎框架。

    Java多執行緒之Condition實現原理原始碼分析

    章節概覽、 1、概述 上面的幾個章節我們基於lock(),unlock()方法為入口,深入分析了獨佔鎖的獲取和釋放。這個章節我們在此基礎上,進一步分析AQS是如何實現await,signal功能。其功能上和synchronize的wait,notify一樣。

    Java多執行緒之ThreadPoolExecutor實現原理原始碼分析

    章節概覽、 1、概述 執行緒池的顧名思義,就是執行緒的一個集合。需要用到執行緒,從集合裡面取出即可。這樣設計主要的作用是優化執行緒的建立和銷燬而造成的資源浪費的情況。Java中的執行緒池的實現主要是JUC下面的ThreadPoolExecutor類完成的。下面

    Vsync垂直同步訊號分發SurfaceFlinger響應執行渲染流程分析

    void SurfaceFlinger::init() { ALOGI( "SurfaceFlinger's main thread ready to run. " "Initializing graphics H/W..."); status_t err;

    Java多執行緒之ReentrantLock實現原理原始碼分析

    章節概覽、 1、ReentrantLock概述 ReentrantLock字面含義是可重入的互斥鎖,實現了和synchronize關鍵字一樣的獨佔鎖功能。但是ReentrantLock使用的是自旋鎖,通過CAS硬體原語指令實現的輕量級的鎖,不會引起上下文切換

    SpringMVC的流程分析—— 整體流程概括

    classes amp 不同 方法 restfu equals 類圖 strong .get SpringMVC的整體概括 之前也寫過springmvc的流程分析,只是當時理解的還不透徹所以那篇文章就放棄了,現在比之前好了些,想著寫下來分享下,也能增強記憶,也希望可以幫助到

    Android系統播放器MediaPlayer原始碼分析

    前言 對於MediaPlayer播放器的原始碼分析內容相對來說比較多,會從Java->JNI->C/C++慢慢分析,後面會慢慢更新。另外,部落格只作為自己學習記錄的一種方式,對於其他的不過多的評論。 MediaPlayerDemo public class MainA

    Android9.0 Activity啟動流程分析

    1、ActivityRecord、TaskRecord、ActivityStack和ActivityDisplay介紹   本篇文章是基於Android refs/tags/android-9.0.0_r8分支的程式碼進行分析的   在分析Activity啟動的原始碼之前先介紹一下Act

    Web前端-Vue專案執行流程分析

    去年年底離職了創業去了哈,把寫部落格的事情給落下了! 一直盯著專案幾乎很少休息,一個月能休息一天算好的啦,煎熬將近一年啊。 都說 “離職窮半年,創業窮三年”,終於嚐到其中滋味!哎。。。現在終於涼了!哈哈! 最近靜下心來,好好反思總結,其中寫部落格這件事,還是不能停止..

    Vue框架專案實戰整理:3、Vue專案執行流程分析

    宣告:本教程不收取任何費用,歡迎轉載,尊重作者勞動成果,不得用於商業用途,侵權必究!!!! 上兩篇講了Vue框架專案實戰整理:1、快速啟動Vue、開發工具介紹 和 Vue框架專案實戰整理:2、Vue環境搭建,今天應該到Vue專案執行流程分析的時候了,為什麼會有這方便的研究

    dart 非同步事件執行流程分析

    深入研究了dart 的非同步事件執行流程。   main() { /// testNoAwait() and testWithCallerAwait() exe order is same. // testNoAwait(); // testWithCal

    [Android6.0][RK3399] 雙屏異顯程式碼實現流程分析

    Platform: RK3399 OS: Android 6.0 Version: v2016.08 本文分為兩部分。 《[RK3399] 雙屏異顯程式碼實現流程分析(一)》為分析 RK video 部分標準的程式碼(base on 2017.

    ContentProvider啟動流程分析

    ## 0x01 扯東扯西的前言&概述 作為安卓設計的四大元件之一,是跨程序共享資料的一把利器,所謂跨程序共享資料,通俗理解就是,應用程式A可以訪問操作應用程式B共享出來的資料,這些共享出來的資料一般都有其對應的URI(統一資源識別符號),那麼就涉及到兩個過程: 提供資料內容的過程: A應用(

    淺談Android之Activity 視窗顯示流程介紹

    7 Activity 視窗顯示流程介紹 Activity 視窗顯示,其實就是Décor View繪製並顯示的過程,但是在繪製之前,Décor View需要先做下面兩件事情: 1)  確定Décor View的大小 2)  對Décor View進行佈局操作,也就是確定Déc

    springboot啟動流程分析

    以springboot 2.0.2.RELEASE版本為例 1.pom.xml引入依賴 <parent> <groupId>org.springframework.boot</groupId>

    JVM——深入解析原理執行機制類載入過程

           隔了好久終於把這篇文章補上了,最近在看《深入理解Java虛擬機器》,一本很不錯的書,必須值得一看。        由於本人對Java類的載入過程一直是一知半解,所以優先看了一下