1. 程式人生 > >OTA--卡刷全包、差分升級包製作、分析(程式碼摘自Google)---2

OTA--卡刷全包、差分升級包製作、分析(程式碼摘自Google)---2

1 .OTA升級流程框架

標準的OTA升級流程包括一下幾個步驟:
1).Android裝置首先會與OTA伺服器進行互動,如果有更新會推送給客戶。推送的資訊常常會包含OTA更新包的下載地址和一些版本資訊。
2).Update程式會將更新包下載到cache分割槽下,並提醒使用者安裝更新。
3).裝置會重啟進入recovery模式,同時啟動recovery分割槽下執行環境,不再啟動boot分割槽下的執行環境。
4).recovery執行環境初始化時會啟動recovery二進位制程式並根據/cache/recovery/command中的命令對更新包進行下一步操作。
5).Recovery執行環境對更新包中/res/key的簽名進行校驗,如果校驗失敗會中斷升級。
6).Recovery二進位制程式會對更新包中的資料進行解壓同時根據解壓出的資料對boot、system、和vender分割槽進行相應的更新。對system分割槽的更新也同時包含了新的recovery分割槽的更新。
7).重啟裝置
a.載入新的boot分割槽,並執行升級後的system分割槽中的二進位制檔案。
b.系統啟動時會同時校驗recovery分割槽,如果recovery與升級時儲存在system分割槽下的資訊不一致會對recovery進行更新。
8).系統更新完成。

2、OTA全包、差分包製作步驟

在原始碼目錄下新建資料夾OTA

1、source build/envsetup.sh。

2、 lunch 然後選擇需要的配置。

3、make 編譯

4、 make otapackage。

5、拷貝out/target/product/(專案名)/ (專案名)-ota-eng.(使用者名稱).zip到OTA並 且重新命名A1.zip

6、拷貝out/target/product/(專案名)/obj/PACKAGING/target_files_intermediates/(專案名)-target_files-eng.(使用者名稱).zip到OTA並重命名A2.zip

7、修改原始碼新增一個log資訊,然後刪除out/target/product/(專案名)/system/build.prop

8、source build/envsetup.sh

9、 lunch 然後選擇配置。

10、make 編譯

11、make otapackage。

12、拷貝out/target/product/(專案名)/ (專案名)-ota-eng.xukang.zip到OTA並且重新命名B1.zip

13、拷貝out/target/product/(專案名)/obj/PACKAGING/target_files_intermediates/(專案名)-target_files-eng.(使用者名稱).zip到OTA並重命名B2.zip

14、製作差分包:

./build/tools/releasetools/ota_from_target_files.py -k build/target/product/security/testkey -i ./OTA/A2.zip ./OTA/B2.zip ./OTA/update.zip (A1.zip B1.zip 不能製作差分包)

15、現在OTA下有五個檔案:A1.zip A2.zip B1.zip B2.zip update.zip

    其中A1.zip    B1.zip 是可以卡刷的全包,但是不能製作差分包

           A2.zip       B2.zip是不能卡刷的全包,但是能製作差分包。

16、拷貝到SD卡

17、平板連結:adb devices,adb reboot fastboot (recovery) 音量上下鍵選擇和power鍵確認,調整進入recover 模式

18、差分包的升級一定要以A1.zip燒製的那個系統版本為基礎
(按一下“音量下”鍵,選擇“apply update from ADB”,然後按下電源鍵確認.

在命令列中輸入”adb sideload update.zip”(ota.zip為自己命名的手機系統升級包)
adb sideload線刷 OTA 升級的方法)
19、System reboot

3、OTA制包過程理論分析,程式碼追蹤

3.1、OTA本質
先以PC機進行類比。假設計算機作業系統裝在C盤,當加電啟動時,載入程式會將C盤的系統程式裝入記憶體並執行,而系統升級或重灌系統,則是將C盤中原來的系統檔案部分或全部重寫。對於手機及其上的Android系統而言,同樣如此,需要一個儲存系統檔案的“硬碟”。
這裡寫圖片描述

圖1 是某款手機的儲存裝置結構圖,其儲存區(紅色框圖部分)分為四部分:SRAM、Nand Flash、SDRAM及外設地址空間。其中Nand Flash中儲存著全部系統資料(通過專門的燒寫工具將編譯後的映象檔案download到Nand Flash中,工具由IC廠商提供),包括boot.img、system.img、recovery.img等,因此Nand Flash即是上文所說的手機上的“硬碟”。圖1最右部分(圖中綠色框圖部分)是Nand Flash儲存區更詳細的劃分,我們將主要關注system分割槽(藍色框圖),因為OTA升級主要是對這部分系統資料的重寫(當然boot分割槽也可升級)。除此之外,藍黑色區域標示的misc分割槽也應值得注意,它在OTA升級中發揮著重要的作用。
OK,一言以蔽之,所謂OTA就是將升級包(zip壓縮包)寫入到系統儲存區,因此我們需要考慮兩個問題,1.升級包是如何生成的?2.升級包是如何寫入到system分割槽的?

3.2、OTA製作程式碼流程圖
這裡寫圖片描述

3.3、整包的製作過程程式碼追蹤
包有整包與差分包之分。顧名思義,所謂整包即包含整個system分割槽中的資料檔案;而差分包則僅包含兩個版本之間改動的部分。利用整包升級好比對電腦進行重作系統,格式分系統分割槽,並將新系統資料寫入分割槽;而利用差分包升級不會格式化system分割槽,只是對其中部分儲存段的內容進行重寫。除升級包之外,製作過程中還會涉及到另一種zip包,程式碼中稱之為target-files zipfile(out/target/product/(專案名)/obj/PACKAGING/target_files_intermediates/ (專案名)-target_files-eng. (使用者名稱).zip),我稱之為差分資源包。首先闡述下整包的製作過程。
系統經過整編後,執行make otapackage命令,即可完成整包的製作,而此命令可分為兩個階段進行。首先執行./build/core/Makefile中的程式碼:

1.  # -----------------------------------------------------------------  
2.  # OTA update package  
3.    
4.  name := $(TARGET_PRODUCT)  
5.  ifeq ($(TARGET_BUILD_TYPE),debug)  
6.    name := $(name)_debug  
7.  endif  
8.  name := $(name)-ota-$(FILE_NAME_TAG)  
9.    
10. INTERNAL_OTA_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip  
11.   
12. $(INTERNAL_OTA_PACKAGE_TARGET): KEY_CERT_PAIR := $(DEFAULT_KEY_CERT_PAIR)  
13.   
14. $(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(OTATOOLS)  
15.         @echo "Package OTA: [email protected]"  
16.         $(hide) ./build/tools/releasetools/ota_from_target_files -v \  
17.            -n \  
18.            -p $(HOST_OUT) \  
19.            -k $(KEY_CERT_PAIR) \  
20.            $(ota_extra_flag) \  
21.            $(BUILT_TARGET_FILES_PACKAGE) [email protected]  
22. .PHONY: otapackage  
23. otapackage: $(INTERNAL_OTA_PACKAGE_TARGET)  
24. # -----------------------------------------------------------------  
        程式碼段1 make otapackage  目的碼生成差分資源包
 這段程式碼作用在於將系統資源(包括system、recovery、boot等目錄)重新打包,生成差分資源包(即target-files zipfile,下文將統一使用“差分資源包”這一概念)。我們可以看下差分資源包中的檔案結構,如下:

這裡寫圖片描述

                圖2 target-files zipfile目錄結構

其中,OTA目錄值得關注,因為在此目錄下存在著一個至關重要的檔案:OTA/bin/updater(後文會有詳述)。生成的差分資源包被傳遞給./build/tools/releasetools/ota_from_target_files執行第二階段的操作:製作升級包。
這裡寫圖片描述
圖3 ./build/tools/releasetools目錄下的檔案
圖3是./build/tools/releasetools目錄下所包含的檔案,這組檔案是Google提供的用來製作升級包的程式碼工具,核心檔案為:ota_from_target_files和img_from_target_files。其中,前者用來製作recovery模式下的升級包;後者則用來製作fastboot下的升級包(fastboot貌似是一種更底層的刷機操作,未過多研究,不再詳述)。其他檔案則是為此二者提供服務的,比如,common.py中包含有製作升級包所需操作的程式碼;edify_generator.py則用於生成recovery模式下升級的指令碼檔案:<升級包>.zip/ META-INF/com/google/android/updater-script。
檔案ota_from_target_files是本文所關注的重點,其中定義了兩個主要的方法:WriteFullOTAPackage和WriteIncrementalOTAPackage。前者用於生成整包,後者用來生成差分包。接著上文,當Makefile呼叫ota_from_target_files,並將差分資源包傳遞進來時,會執行WriteFullOTAPackage。此方法完成的工作包括:(1)將system目錄,boot.img等檔案新增到整包中;(2)生成升級包中的指令碼檔案:<升級包>.zip/META-INF/com/google/android/updater-script;(3)將上文提到的可執行檔案:OTA/bin/updater新增到升級包中:META-INF/com/google/android/updater-script。摘取部分程式碼片段如下:

1.  script.FormatPartition("/system")  
2.    script. FormatPartition ("/system")  
3.    script.UnpackPackageDir("recovery", "/system")  
4.    script.UnpackPackageDir("system", "/system")  
5.    
6.    (symlinks, retouch_files) = CopySystemFiles(input_zip, output_zip)  
7.    script.MakeSymlinks(symlinks)  
8.    if OPTIONS.aslr_mode:  
9.      script.RetouchBinaries(retouch_files)  
10.   else:  
11.     script.UndoRetouchBinaries(retouch_files)  
程式碼2 WriteFullOTAPackage程式碼片段生成全包

其中的script為edify_generator物件,其FormatPartition、UnpackPackageDir等方法分別是向指令碼檔案update-script中寫入格式化分割槽、解壓包等指令。

1.  def AddToZip(self, input_zip, output_zip, input_path=None):  
2.      """Write the accumulated script to the output_zip file.  input_zip 
3.      is used as the source for the 'updater' binary needed to run 
4.      script.  If input_path is not None, it will be used as a local 
5.      path for the binary instead of input_zip."""  
6.    
7.      self.UnmountAll()  
8.    
9.      common.ZipWriteStr(output_zip, "META-INF/com/google/android/updater-script",  
10.                        "\n".join(self.script) + "\n")  
11.   
12.     if input_path is None:  
13.       data = input_zip.read("OTA/bin/updater")  
14.     else:  
15.       data = open(os.path.join(input_path, "updater")).read()  
16.     common.ZipWriteStr(output_zip, "META-INF/com/google/android/update-binary",  
17.                        data, perms=0755)  
     程式碼段3  edify_generator中的AddToZip方法

WriteFullOTAPackage執行的最後會呼叫此方法。將資源差分包中OTA/bin/updater檔案copy到升級包中META-INF/com/google/android/update-binary。此檔案是OTA升級的關鍵,其將在recovery模式下被執行,用來將程式碼段2中生成的指令轉換為相應的函式去執行,從而完成對系統資料的重寫。

3.4、差分包的製作

生成差分包呼叫的是檔案./build/tools/releasetools/ota_from_target_files中的WriteIncrementalOTA方法,呼叫時需要將兩個版本的差分資源包作為引數傳進來,形如:

./build/tools/releasetools/ota_from_target_files –n –i ota_v1.zip ota_v2.zip update.zip
其中,引數n表示忽略時間戳;i表示生成增量包(即差分包);ota_v1.zip與ota_v2.zip分別代表前後兩個版本的差分資源包;而update.zip則表示最終生成的差分包。
WriteIncrementalOTA函式會計算輸入的兩個差分資源包中版本的差異,並將其寫入到差分包中;同時,將updater及生成指令碼檔案udpate-script新增到升級包中。
製作完升級包後,之後便是將其寫入到相應儲存區中,這部分工作是在recovery模式下完成的。之前的幾篇筆記亦有描述,recovery模式下通過建立一個新的程序讀取並執行指令碼檔案META-INF/com/google/android/updater-script。見如下程式碼:

1.  const char** args = (const char**)malloc(sizeof(char*) * 5);  
2.  args[0] = binary;  
3.  args[1] = EXPAND(RECOVERY_API_VERSION);   // defined in Android.mk  
4.  char* temp = (char*)malloc(10);  
5.  sprintf(temp, "%d", pipefd[1]);  
6.  args[2] = temp;  
7.  args[3] = (char*)path;  
8.  args[4] = NULL;  
9.    
10. pid_t pid = fork();  
11. if (pid == 0) {  
12.     close(pipefd[0]);  
13.     execv(binary, (char* const*)args);  
14.     _exit(-1);  
15. }  
16. close(pipefd[1]);  
    程式碼段4 建立新程序安裝升級包

分析程式碼之前,首先介紹Linux中函式fork與execv的用法。
pid_t fork( void)
建立新的程序,fork呼叫的一個奇妙之處就是它僅僅被呼叫一次,卻能夠返回兩次,它可能有三種不同的返回值:
  1)在父程序中,fork返回新建立子程序的程序ID;
  2)在子程序中,fork返回0;
  3)如果出現錯誤,fork返回一個負值;
在fork函式執行完畢後,如果建立新程序成功,則出現兩個程序,一個是子程序,一個是父程序。在子程序中,fork函式返回0,在父程序中,fork返回新建立子程序的程序ID。我們可以通過fork返回的值來判斷當前程序是子程序還是父程序(http://os.chinaunix.net/a2012/0203/1306/000001306508.shtml)。
int execv(const char *progname, char *const argv[])
execv會停止執行當前的程序,並且以progname應用程序替換被停止執行的程序,程序ID沒有改變。
progname: 被執行的應用程式。
argv: 傳遞給應用程式的引數列表, 注意,這個陣列的第一個引數應該是應用程式名字本身,並且最後一個引數應該為NULL,不參將多個引數合併為一個引數放入陣列。
程式碼4見於bootable/recovery/install.c的try_update_binary函式中,是OTA升級的核心程式碼之一。通過對fork及execv函式的介紹可知,程式碼4建立了一個新的程序並在新程序中執行升級包中的META-INF/com/google/android/updater-binary檔案(引數binary已在此前賦值),此檔案將按照META-INF/com/google/android/updater-script中的指令將升級包裡的資料寫入到儲存區中。OK,我們來看下META-INF/com/google/android/updater-binary檔案的來歷。
在原始碼的./bootable/recovery/updater目錄下,存在著如下幾個檔案:
這裡寫圖片描述
圖4 ./bootable/recovery/updater目錄
通過檢視Android.mk程式碼可知,檔案install.c、updater.c將會被編譯為可執行檔案updater存放到目錄out/target/product//obj/EXECUTABLES/
updater_intermediates/中;而在生成差分資源包(target-files zipfile)時,會將此檔案新增到壓縮包中。

1.  built_ota_tools := \  
2.      $(call intermediates-dir-for,EXECUTABLES,applypatch)/applypatch \  
3.      $(call intermediates-dir-for,EXECUTABLES,applypatch_static)/applypatch_static \  
4.      $(call intermediates-dir-for,EXECUTABLES,check_prereq)/check_prereq \  
5.      $(call intermediates-dir-for,EXECUTABLES,sqlite3)/sqlite3 \  
6.      $(call intermediates-dir-for,EXECUTABLES,updater)/updater  
     程式碼段5 Makefile中定義的變數built_ota_tools
1.  $(hide) mkdir -p $(zip_root)/OTA/bin  
2.      $(hide) $(ACP) $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(zip_root)/OTA/  
3.      $(hide) $(ACP) $(PRIVATE_OTA_TOOLS) $(zip_root)/OTA/bin/  
    程式碼段6 複製built_ota_tools工具到差分資源包

如程式碼段5,Makefile中定義了執行OTA所需要的一組工具(built_ota_tools),其中便包括由圖4中檔案編譯而成的檔案updater;而在生成差分資源包時,會將這組工具拷貝到差分資源包的OTA/bin目錄中(見程式碼段6);在生成升級包時(無論是執行WriteFullOTAPackage還是WriteIncrementalOTAPackage),最後都會呼叫edify_generator的AddToZip方法,將updater新增到升級包中(更名為”META-INF/com/google/android/update-binary”);最終在recovery模式下被執行,這便是其來龍去脈。而關於updater的執行,也大致的描述下吧。
由前文可知,updater主要由bootable/recovery/updater目錄下的install.c和updater.c編譯而成,主函式位於updater.c。其中,在install.c中定義了讀寫系統儲存區的操作函式(這才是重寫系統資料的真正程式碼)並將這些函式與updater-script中的指令對映起來。而在updater.c會首先裝載install.c定義的函式,之後便解析升級指令碼updater-script,執行其對應的操作命令。與此同時,執行updater的程序還會與父程序通訊,通知父程序進行UI的相關操作(程式碼見bootable/recovery/install.c中的try_update_binary函式)。

參考文件:

相關推薦

OTA--升級製作分析程式碼摘自Google---2

1 .OTA升級流程框架 標準的OTA升級流程包括一下幾個步驟: 1).Android裝置首先會與OTA伺服器進行互動,如果有更新會推送給客戶。推送的資訊常常會包含OTA更新包的下載地址和一些版本資訊。 2).Update程式會將更新包下載到cac

拉鉤網易淘寶移動端rem佈局分析轉載非原創

從網易與淘寶的font-size思考前端設計稿與工作流 本文結合自己對網易與淘寶移動端首頁html元素上的font-size這個屬性的思考與學習,討論html5設計稿尺寸以及前端與設計之間協作流程的問題,內容較多,但對你的技術和工作一定有價值,歡迎閱讀和點評:)。 這

【dataframe】增加時間序列填充內容爾積去除無效值排序

import pandas as pd import time data = pd.read_csv("Airpassengers.csv") 快速增加時間序列軸 df = pd.DataFrame() df['value'] = data['value'] df['se

單端輸入

單端訊號: 單端訊號(single-end)是相對於差分訊號而言的,單端輸入指訊號有一個參考端和一個訊號端構成,參考端一般為地端。   ADC單端輸入 比如說UART232串列埠中,傳送端TXD,接收端RXD,參考端是地,GND,是典型的單端訊號輸入輸出。 單端輸入時,

Luogu3527 POI2011 Meteors 整體二分樹狀數組

back getc owb main its 題目 sdi num ons 傳送門 比較板子的整體二分題目,時限有點緊註意常數 整體二分的過程中將時間在\([l,mid]\)之間的流星使用樹狀數組+差分進行維護,然後對所有國家查看一遍並分好類,遞歸下去,記得消除答案在\(

Luogu3527 POI2011 Meteors 整體二分樹狀陣列

傳送門 比較板子的整體二分題目,時限有點緊注意常數 整體二分的過程中將時間在\([l,mid]\)之間的流星使用樹狀陣列+差分進行維護,然後對所有國家檢視一遍並分好類,遞迴下去,記得消除答案在\([mid+1,r]\)的詢問中時間在\([l,mid]\)的流星操作的貢獻 注意:可能存在某一段時間某一

JAVAEE——BOS物流項目05:OCUploadPOIpinyin4J重構頁代碼區添加combobox

sof 抽取 mil get 輸入 數據庫操作 過程 public path 1 學習計劃 1、實現區域導入功能 n OCUpload一鍵上傳插件使用 n 將文件上傳到Action n POI簡介 n 使用POI解析Excel文件 n 完成數據庫操作 n 使用pinyin4

雲端一體化升級,AliOS Things物聯網升級“利器”

alibaba 高級 雲安全服務 創建 elf cto 軟件架構 src blog 摘要: 隨著物聯網的日益發展,OTA升級逐漸成為物聯網設備的剛性需求,目前物聯網設備種類繁多,但並未提供統一的OTA升級方案,針對日益發展的物聯網設備,開發者迫切需要一套雲端一體化的OTA升

雲端一體化升級,AliOSThings物聯網升級“利器”

fop 種類 text 51cto 提高 操作 編譯工具 完整性 命令 摘要: 隨著物聯網的日益發展,OTA升級逐漸成為物聯網設備的剛性需求,目前物聯網設備種類繁多,但並未提供統一的OTA升級方案,針對日益發展的物聯網設備,開發者迫切需要一套雲端一體化的OTA升級方案來滿足

(Java) ---- Eclipse快捷鍵文件註釋和製作生成和匯入jar

【Eclipse快捷鍵】 (1)ctrl+T  檢視類的繼承樹。 (2)Ctrl+點選類名或者方法名,來檢視原始碼。 JDK (JRE(JVM,執行時所需要的核心類庫),開發工具(javac...)) 【Java中文件的註釋和製作】 /** + 回車(Enter

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

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

隱私若干基本知識點介紹

                 為解決當前資訊越來越發達的社會所帶來的使用者隱私洩露問題,本人所研究的差分隱私模型是一種被廣泛認可的嚴格的隱私保護模型。它通過對資料新增干擾噪聲的方式保護所釋出資料中

46求1+2+3+...+n,要求不能使用乘除法forwhileifelseswitchcase等關鍵字及條件判斷語句A?B:C

closed else while spl 判斷語句 stat 條件 執行 ret 思路:循環或者遞歸都有個結束條件和執行條件。用&&短路與代替。 //短路與&&;就是只有前一個條件滿足才可以去判斷第二個條件。 //遞歸的出口

C# 窗體 切換重復顯示等遺留問題解決第五天

event 學校 切換 ner 父窗體 所有 var smd 彈出 一、解決同一窗體多次點擊重復顯示BUG (1)點擊彈出學校窗體 1 #region 彈出學校窗體 2 /// <summary&g

查看Linux內核版本命令兩種方法

use proc color tex 2.6 distrib oot lin hat 一、查看Linux內核版本命令(兩種方法):1、cat /proc/version[[email protected]CentOS home]# cat /proc/versio

第二周:神經網絡的編程基礎----------2編程作業常見問題與答案Programming Assignment FAQ

sort sign 常見問題 keep 什麽 有變 圖標 更新 無限循環 Please note that when you are working on the programming exercise you will find comments that say "#

區助手各版本比較圖文詳解

fail str ati width weixin edi 匯聚 個人博客 ali     不多說,直接上幹貨!   分區助手擁有三個版本,專業版,綠色版和WinPE版。這裏對其的版本比較如下:   詳情,見http://www

? 一cocos2dx之如何優化內存使用高級篇

cell 一個 mpc 情況 sha 優化方案 ali 等等 所有 一、內存優化原則 為了優化應用內存,你應該知道是什麽消耗了你應用的大部分內存,答案就是Texture(紋理)!它幾乎占據了90%的應用內存。那麽我們應該盡力去減小我們應用的紋理內存使用,否則我們的應用

Fidder詳解-抓取HTTPS清求Web/App分析靠譜篇

可能 clas 請求 設置代理 cer port 關閉 lan str 為什麽要學Fidder抓包? 學習接口,必須要學http協議,不要求您對協議的掌握有多深。只是希望你能夠了解什麽是協議、協議的報文、狀態碼等等!本文通過抓包工具Fidder帶你進入接口的大門。我們通過

線程對稱多處理和微內核OS 筆記三

復雜 另一個 相同 構造 按順序 技術 多進程 優先級 特權 線程、對稱多處理 ? 這一部分繼續深入探討與進程管理相關的高級概念並了解多處理機的對稱多處理技術。 進程和線程 到目前為止提出的進程的概念包含兩個特點: 資源所有權 存放進程映像的虛擬地址空間 調度/執行