OTA-扫盲
文章目錄
- 前言
- 一、種類劃分
- 三、OTA升級log
- 三、OTA包制作
- full包
- 差分包
- 總結
前言
OTA(over the air)一種通過空中下載技術下載升級的方式,指的通常是使用wifi或者數據流量的方式從服務器中將升級包下載到本地升級的一種方式;但是本地使用OTA包的升方式,我們也可以稱之為OTA升級(概念的擴展),簡單理解起來只要是使用制作出來的升級包去升級的過程我們統稱為OTA升級。
一、種類劃分
按升級方式的不同,可分為:在線升級和本地升級
按升級載體的不同,可分為:在線升級、T卡升級、adb升級
按升級包類型不同,可分為:增量(incremental update)升級和整包(full update)升級
命名方式:差分包、增量包、升級包、降級包、整包
1.1 在線升級
在線升級簡單來說,就是將升級包上傳至服務器端,然后機器通過連接wifi或者數據流量從服務器端將升級包下載到手機中進行升級的一種方式;這種升級方式需要配置對應的指紋信息或者IMEI號等,保證手機可搜索到包,以及搜索到包的正確性,這種方式是用戶通常升級版本最常用的方式,整個流程需要經過對應的服務器端->framework框架層->recovery升級階段。
1.2 T卡升級
T卡升級其實也可以稱為本地升級,它是將升級包放置到T卡中進行升級的一種方式,通常的T卡升級可以從兩個入口進行升級,分別是:1、正常模式下的設置模塊自定義的system update升級入口;2、進入recovery模式下選擇”apply update from sdcard”
1.3 sideload升級
adb升級其實也是本地升級的一種,因為升級包都是離線狀態下取到的,不需要從服務器端下載,它的方式其實也有兩種:1、正常模式下,保證adb端口正常直接執行adb reboot recovery sideload xx/xx/xx.zip;2、recovery模式下,選擇”apply update from adb”菜單后,通過執行adb sideload xx/xx/xx.zip命令進行升級。
1.4 升級結果
1.4.1 關注升級過程:
在安卓7.0之前,升級的過程谷歌原生UI主要以綠色小機器人作為標記,當然OEM廠商也可以自己design,這種谷歌原生方式在升級過程中如果出現報錯會有小機器人倒下等提示,如果是直接進recovery模式會有log提示升級失敗字樣,這種情況一定可以確定升級失敗(下圖是在項目上找到的升級失敗的截圖,ui同事已經對其做了替換,利用這種ui提示代表升級失敗)
1.4.2 關注升級結果:
當第一種情況已經可以確認升級失敗了,那么第二點就不用參考,否則在第一種情況未出現異常后,需要關注第二點的表現。升級后的結果主要指的是升級完成后,重啟開機,如果能夠正常開機,再檢查對應各項內容是否升級成功,比如版本號是否更新、應用是否更新等情況。如果升級完成之后,無法開機,可以直接將機器拿到升級模塊負責同事,檢查升級過程是否有異常,如果沒有異常交由開機啟動模式分析為什么無法開機,升級同事負責協助;如果升級完成后,能夠正常開機,檢查對應的版本號等已更新,但是會出現應用報錯、或者頁面布局存在異常,需要將問題直接反饋到模塊負責同事
二、OTA升級log
2.1 MTK上層log
適用場景:針對的就是在線升級方式導致的升級失敗或者是本地T卡升級從設置模塊的system update入口選擇升級導致的升級失敗,對于這兩種方式升級失敗問題,要求升級前打開MTK log進行升級,升級失敗后提供對應的MTK LOG,再通俗點理解就是凡是在正常模式下啟動的升級流程都需要提供MTK LOG。
抓取方法:確認版本是否是user版本。userdebug版本和eng版本默認開啟MTK LOG,如果是user版本,可以使用工程指令:調出log界面,選擇啟動即可。默認將mtklog存放到內置sdcard里面去了,其實如果你插入外置T卡,也可以選擇將log保存在外置T卡里面,除此之外還可以選擇保存哪些log,假設是保存在內置T卡里面,可以使用MTP的方式拷貝MTKlog出來或者是執行命令:adb pull /sdcard/mtklog d:mtklog\即可,存放的地方可以自己定義,抓取后再出現異常后,提供給研發同事。
2.2 Recovery升級log
解釋:主要指的就是升級過程中打印出來的log,該log是進入recovery模式后打印出來的,與正常模式下的mtklog是完全不同的,存放于cache分區中,需要單獨抓取。
適用場景:任何升級失敗場景
抓取方法1:進人recovery模式提供log截圖,操作方法是進人recovery界面,或者當前已處在recovery模式下的時候,找到下面的菜單位置,按power鍵進入,進入后發現會有下面截圖所示,有last_log和last_kmsg字樣,對于簡單的升級來說,只需要進入last_log,按音量下鍵往下翻頁,直到看到類似failed字樣,或者是進度條拉到大概90%到100%左右處截圖提供,有些時候last_log會不止一個,有last_log1/last_log2等,這個時候需要測試同事同時關注下last_log和last_log1。
抓取方法2:提供cache分區,這種方式可以提供更全的升級log,需要掌握下載工具dump cache分區的操作。
2.3 cache分區dump流程
A、打開工具界面后,選擇ReadBackA、打開工具界面后,選擇ReadBack
B、選擇ReadBack后會看到下面的截圖界面,按照提示選擇Add
C、選擇 Add之后,會出現下面截圖所示界面,雙擊截圖位置
D、雙擊之后會彈出一個框,需要填寫鏡像文件的名稱和存放位置,保存
E、保存按鈕點擊后,會再次彈出新的框,如下所示,最關鍵的地方也是在這里,這里需要填寫dump的鏡像文件的起始地址和size大小,一開始默認都是全0
F、鏡像文件的起始地址和長度可以從下載版本中的scatter.txt里面獲取,如dump cache分區,就需要找到cache分區所在位置,填寫如下兩個值到對應上面的框圖中
G、填寫后,就如下圖所示,點擊OK按鈕
H、 配置完成后,就可以點擊Read Back按鈕,成灰顯狀態后,手機關機插USB,即可完成分區的dump過程,最終dump完成后如下截圖所示,從之前存放的位置選擇dump出來的cache.img提供即可
三、OTA包制作
3.1 full包編譯
方式1:
A、執行source tran_setenv.sh xx user/userdebug/eng efuse
B、編譯整個工程,執行make -j24 2>&1 | tee build.log
C、簽名鏡像文件,執行./vendor/mediatek/proprietary/scripts/sign-image/sign_image.sh【重點:這一步一定要先操作】
D、執行做包指令,make otapackage -j24 2>&1 | tee ota.txt,按照正常的這種流程操作完畢后,會在對應的項目路徑下面生成對應的full包
方式2:
A、make otapackage命令除了是生成full包之外,還會在對應的該目錄下生成target_files目錄,如果沒有執行make otapackage這一命令,是不會有該目錄的,該目錄下面的zip包也是用來制作差分包的基礎版本
B、有了上述的target包之后,就可以直接通過調用腳本指令制作full包,執行: ./build/tools/releasetools/ota_from_target_files -k vendor/commonconfig/security/releasekey -s vendor/mediatek/proprietary/scripts/releasetools/mt_ota_from_target_files.py full_xx-target_files-xx.zip Tcard.zip
3.2 full包生成
build/core/Makefile:
定義了一個偽目標otapackage,它依賴于INTERNAL_OTA_PACKAGE_TARGET,而該文件就是制作OTA整包最后的生成文件,它的命名方式如下,生成位置在PRODUCT_OUT目錄下,命名為$(name).zip,而name是等于$(name)-ota-$(FILE_NAME_TAG),主要有三部分組成:TARGET_PRODUCT,這個在一開始source的時候就會確定,TARGET_BUILD_TYPE一般情況下都是定義成release,FILE_NAME_TAG這個變量在main.mk里面有定義,會根據HAS_BUILD_NUMBER宏來進行區分,最后本地生成的整包名字
BUILT_TARGET_FILES_PACKAGE的生成: 它是生成整包所需的中間文件。最后生成位置位于路徑out\target\product\xx\obj\PACKAGING\target_files_intermediates\xx-target_files-xx.zip
(1)清理以前殘存的目錄和文件,并創建$(zip_root)目錄,即對應的out\target\product\xx\obj\PACKAGING\target_files_intermediates\<product>-target_files-xx
(2)創建$(zip_root)/RECOVERY目錄,把out/target/product/xx/recovery/root下的所有文件和目錄拷貝到$(zip_root)/RECOVERY,還有out/target/product/xx目錄下的其它目錄文件如cmdline/second/kernel等到對應的$(zip_root)/RECOVERY目錄下
(3)創建$(zip_root)/BOOT目錄,并拷貝對應的內容到該目錄下,同 recovery,后面類似的還會創建SYSTEM/RADIO/VENDOR/OTA/META等目錄,其中需要重點關注的是META和OTA目錄,META目錄下面會生成很多txt文件,這些文件對于制作升級包會強相關,OTA目錄下面主要是包含了升級過程中需要的升級函數實現的可執行文件
…………………… ……………………
ota_from_target_files.py腳本
(1) main函數參數解析
(2) 從中間的zip包里面的META/misc_info.txt中 解析出對應的參數,例如key,tool_extensions等,OPTIONS.extracted_input就是前面Makefile中通過” --extracted_input_target_files”指定的target中間包,其中解析的misc_info.txt里面的內容主要是賦給OPTIONS.info_dict;
(3) 從OPTIONS對里找到tool_extensions賦值給OPTIONS.device_specific,這是假定如果沒有指定”-s”參數的話,如果指定了就直接從指定的py腳本中獲取
(4) input_zip為上文中的zip包,out_zip為最終生成的臨時zip包,對于整包的話會調用WriteFullOTAPackage(input_zip, ?output_file=args[1])函數來生成
(5)調用SignOutput簽名臨時包,生成最終的全包升級包
?WriteFullOTAPackage函數實現
(1) 生成Edify腳本,主要在EdifyGenerator.py里面實現,在這里面實現的都是各種升級過程中的處理命令,寫到對應的update-script腳本里面
(2) 調用GetPackageMetadata函數獲取對應的元數據內容,最后會將這些內容寫到升級包里面
(3) 獲取對應的版本里面的編譯時間,為日后升級過程中做校驗使用,也就是說T卡包在升級的時候是會校驗時間戳的,它不允許后往后倒退升級
(4)設置對應的進度條處理腳本,通過script的ShowProgress實現
(5)獲取boot分區內容,對system和vendor分區進行處理生成對應升級所需內容,其中AddCompatibilityArchiveIfTrebleEnabled主要是將system和vendor下面的一些 xml文件寫入升級包中,這些xml文件是treble使能后新增的,主要用于升級過程中校驗,在升級過程中會獲取手機里面的信息與之作比較
(6)對boot分區進行整個鏡像的內容寫入,在升級過程中會整個覆蓋寫入boot分區
(7)preloader、lk、modem等其它特殊分區的處理
releasetools.py腳本
A、根據是否是整包往升級包中type.txt里面寫入對應的值,讀取OTA目錄下面的ota_update_list.txt內容寫入到scatter.txt里面,放入升級包中,對于type.txt文件最后升級的時候其實并沒有應用到,但是scatter.txt里面在升級過程中會有用到
B、check-bootloader_path函數主要針對preloader做處理,它會判斷對應的存儲芯片類型是否是ufs,通過ro.vendor.mtk_ufs_support=1宏來決定,這樣做的目的是因為ufs和emmc對應的preloader的設備路徑是不同的,如果不做區分升級preloader分區的時候就存在問題
C、AddOTAImage_Items函數就是真正對除常用分區外其他分區進行處理的關鍵部分,它會讀取ota_update_list.txt里面待升級的分區,然后根據不同類型進行區分,最終寫入到升級包中腳本中,主要就是區分兩類,其中dtbo md1img spmfw vbmeta作為一類,直接寫入對應的設備路徑;sspm tee scp preloader需要同時寫入對應的源和備份設備路徑,也就是所定義的1和2
(8)判斷是否有額外腳本選項指定,以及判斷是否指定了擦除用戶數據,也就是-w,如果指定了的話,調用script的FormatPartition函數對data分區進行格式化的寫命令處理
(9)調用FinalizeMetadata函數進行處理,這里面會將metadata文件寫入升級包中的META-INF/com/android/metadata位置,再調用SignOutput函數完成版本的簽名操作,最終到此完成這個升級包的制作
3.3?差分包編譯
所謂的差分包,其實就是使用兩個版本之間的差異生成一種只針對差異化更新的增量升級包,這種升級包與full包的不同之處在于它更小,而差異化的地方多通過patch的方式升級,升級速度更快,對于手機所要求的存儲空間低。要生成差分包,就需要有兩個不同版本的target文件,因此上述full包的操作流程需要在兩個版本間都執行過一次,獲取到最終兩個版本間的target文件,再通過target文件進行差分操作。
編譯命令: ./build/tools/releasetools/ota_from_target_files -k vendor/commonconfig/security/releasekey -s vendor/mediatek/proprietary/scripts/releasetools/mt_ota_from_target_files.py -i full_xx-target_files-xx.zip full_xxx-target_files-xxx.zip Increment-ota.zip
差分包的命令目前O版本和P版本存在差異:
O版本:. ./build/tools/releasetools/ota_from_target_files -k vendor/commonconfig/security/releasekey -s vendor/mediatek/proprietary/scripts/releasetools/mt_ota_from_target_files -i V1.zip V2.zip update.zip
P版本:./build/tools/releasetools/ota_from_target_files -k vendor/commonconfig/security/releasekey -i V1.zip V2.zip update.zip 接下來就上述指令簡單分析下差分包的生成流程,其中”藍色字體”表示選項可添加也可不添加,”紅色參數”表示必須添加。同full包一樣,差分包的生成也主要是通過ota_from_target_files.py腳本生成,只不過在處理的地方稍有差異。
3.4 差分包生成
main主函數執行過程:
(1)從參數和環境中解析OPTIONS,同full包,前面提到過”-k”參數是可有可無的,但是如果指定的話,就會將指定的路徑key賦給OPTIONS.package_key,同時如果指定了”-i”參數就將后面跟著的版本賦給OPTIONS.incremental_source
(2)加載讀取升級包中的misc_info.txt里面的內容,同上full包,只不過相較于full包,它這個工作需要做兩次,會同時獲取源target和目標target分別賦給OPTIONS.target_info_dict以及OPTIONS.info_dict后面在升級包處理過程中都會用到
(3)調用common.py腳本里面的UnzipTemp解壓函數解壓target zip文件,同時也會載入對應是device_specific腳本,如果沒有通過-s命令指定的話,就會默認從META目錄下面獲取,將releasetools.py作為默認腳本
(4)再次解壓source zip,調用WriteBlockIncrementalOTAPackage腳本實現差分包的處理
WriteBlockIncrementalOTAPackage執行流程:
(1)生成Edify腳本,主要在EdifyGenerator.py里面實現,在這里面實現的都是各種升級過程中的處理命令,寫到對應的update-script腳本里面
(2)獲取對應的源和目標boot內容,主要是從IMAGES/目錄下獲取對應的boot.img內容,同時獲取對應的目標recovery內容
(3)調用common.py腳本的GetSparseImage函數獲取對應的system內容中的block數據,源target和目標target都要獲取分別賦給system_src和system_tgt,最后調用common.py腳本中的BlockDifference類對其進行差異化block處理,最終調用的是blockimgdiff.py里面的BlockImageDiff函數,這里面集成的都是基于bsdiff的算法
(4)接下來針對vendor分區的處理過程,它的處理方式和system分區一樣,只不過執行的時候會首先判斷是否存在分區,由于block的升級在安卓6.0就支持了,而當時其實谷歌對于treble這塊還未有介紹,所以vendor分區作為一個非必須存在分區,主要由芯片廠商或者手機廠商自行決定,而谷歌的代碼則會照顧到vendor分區有或者無的情況,因此添加了是否存在vendor分區的判斷,這個判斷一直沿用至今也沒有去掉
(5)接下來會調用WriteFingerprintAssertion函數獲取對應的fingerprint寫入腳本中,升級過程中會去校驗該屬性,同時會根據system和vendor在差分過程中所要求的cache size大小追加到size列表里面,后面會將要求的值寫入到對應的metadata里面,在升級過程中也會檢測cache分區空間的剩余大小是否滿足要求
(6)接下來對boot分區進行處理,會去計算source boot 和target boot之間的差異性,如果差異太大導致出錯就會將boot分區作為整個鏡像文件升級處理,反之則會直接根據source和target的boot.img進行差分生成boot.img.p寫入到升級包中,升級的時候就會將boot分區做patch升級,在升級前還是會做patch check的動作,檢查手機版本中的哈希是否滿足要求,如果不一致則報錯處理,這就要求升級包的制作一定要是下載到手機中的源版本和另一個目標版本之間的差分
(7)對于非主要的ap側分區以及引導分區的升級都在對應的device_specific腳本里面的IncrementalOTA_InstallEnd里面完成,這個過程前面在full包中有介紹,過程類似,差異性也有但是不多,感興趣可以自己去看代碼,不作重復介紹(7)對于非主要的ap側分區以及引導分區的升級都在對應的device_specific腳本里面的IncrementalOTA_InstallEnd里面完成,這個過程前面在full包中有介紹,過程類似,差異性也有但是不多,感興趣可以自己去看代碼,不作重復介紹
(8)和full包不同之處還有一點,它支持所謂的降級處理,也就是制作升級包的時候指定--downgrade參數,指定該參數可以允許你升級到一個比你源版本時間舊的版本,但是一個重要影響它會擦除data分區,即用戶數據,所以該選項慎用
(9)最后一步也是和full包一樣,需要對其進行簽名操作,實現同上full包具體過程也可以查看FinalizeMetadata的實現
簽名命令:
java -Xmx2048m -Djava.library.path=out/host/linux-x86/lib64 -jar out/host/linux-x86/framework/signapk.jar -w vendor/tran_os/security/releasekey.x509.pem vendor/tran_os/security/releasekey.pk8 /tmp/tmpMvN4L7 out/target/product/ka7_h8024/full_ka7_h8024-ota-1542863682.zip
總結
對于初學者,此文章可以幫忙快速掃盲,當然任何技術上的精進都是建立在基礎之上。如果一些簡單的名詞或者說法都不清楚,一切都是空談。了解此篇后,就可以更深層次的學習,加油,未來可期!
總結
- 上一篇: adnroid 系统OTA升级
- 下一篇: java 搭建ota服务器_OTA配置服