OTA 包內部

系統從bootable/recovery/updater建立更新程式二進位文件,並在 OTA 套件中使用它。

該套件本身是一個 .zip 檔案( ota_update.zipincremental_ota_update.zip ),其中包含可執行二進位檔案META-INF/com/google/android/update-binary

Updater 包含多個內建函數和一個可擴展腳本語言 ( edify ) 的解釋器,該解釋器支援典型更新相關任務的命令。更新程式在套件 .zip 檔案中尋找META-INF/com/google/android/updater-script檔案中的腳本。

注意:使用 edify 腳本和/或內建函數不是常見活動,但如果您需要偵錯更新文件,它會很有幫助。

Edify文法

edify 腳本是一個單一表達式,其中所有值都是字串。空字串在布林上下文中為false ,所有其他字串為true 。 Edify 支援以下運算子(具有通常意義):

(expr )
 expr + expr  # string concatenation, not integer addition
 expr == expr
 expr != expr
 expr && expr
 expr || expr
 ! expr
 if expr then expr endif
 if expr then expr else expr endif
 function_name(expr, expr,...)
 expr; expr

任意字串az、AZ、0-9、_、:、/、。這不是保留字,被視為字串文字。 (保留字是if else then endif。 )字串文字也可以出現在雙引號中;這是如何建立帶有空格和其他不在上述集合中的字元的值。 \n、\t、\" 和 \\ 在引號的字串中用作轉義符,\x ##也是如此。

&& 和 ||運營商短路;如果邏輯結果由左側決定,則不評估右側。以下是等效的:

e1 && e2
if e1 then e2 endif

這 ;運算符是一個序列點;這意味著首先評估左側,然後評估右側。它的值是右側表達式的值。分號也可以出現在表達式之後,因此效果模擬 C 風格的語句:

prepare();
do_other_thing("argument");
finish_up();

內建功能

大多數更新功能包含在可供腳本執行的函數中。 (嚴格來說,這些是巨集而不是 Lisp 意義上的函數,因為它們不需要計算所有參數。)除非另有說明,否則函數在成功時傳回true ,在錯誤時傳回false 。如果您希望出現錯誤而中止腳本的執行,請使用abort()和/或assert()函數。更新程式中可用的功能集也可以擴展以提供特定於裝置的功能

abort([ msg ])
使用可選的msg立即中止腳本的執行。如果使用者開啟了文字顯示,訊息將出現在復原日誌和螢幕上。
assert( expr [, expr , ...])
依序評估每個expr 。如果有任何一個為 false,則立即中止​​執行,並顯示訊息「斷言失敗」和失敗表達式的來源文字。
apply_patch( src_file , tgt_file , tgt_sha1 , tgt_size , patch1_sha1 , patch1_blob , [...])
將二進位補丁應用於src_file以產生tgt_file 。如果所需的目標與來源相同,請為tgt_file傳遞“-”。 tgt_sha1tgt_size是預期的最終 SHA1 雜湊值和目標檔案的大小。其餘參數必須成對出現:SHA1 雜湊(40 個字元的十六進位字串)和 blob。 blob 是當來源檔案的目前內容具有給定 SHA1 時要套用的修補程式。

修補是以安全的方式完成的,可確保目標檔案具有所需的 SHA1 雜湊值和大小,或不受影響 - 它不會處於不可恢復的中間狀態。如果在打補丁過程中程序被中斷,目標檔案可能處於中間狀態;快取分區中存在副本,因此重新啟動更新可以成功更新該檔案。

支援特殊語法將記憶體技術設備 (MTD) 分區的內容視為文件,從而允許修補原始分區,例如引導分區。要讀取 MTD 分割區,您必須知道要讀取多少數據,因為該分割區沒有檔案結束概念。您可以使用字串“MTD: partition : size_1 : sha1_1 : size_2 : sha1_2 ”作為檔案名稱來讀取給定分割區。您必須指定至少一對(size, sha-1) ;如果您希望閱讀的內容有多種可能性,您可以指定多個。

apply_patch_check( filename , sha1 [, sha1 , ...])
如果檔案名稱的內容或快取分區中的暫存副本(如果存在)的 SHA1 校驗和等於給定sha1值之一,則傳回 true。 sha1值指定為 40 個十六進位數字。此函數與sha1_check(read_file( filename ), sha1 [, ...])不同之處在於它知道檢查快取分區副本,因此即使檔案因apply_patch() update中斷而損壞, apply_patch_check()也會成功。
apply_patch_space( bytes )
如果至少有位元組的暫存空間可用於套用二進位補丁,則傳回 true。
concat( expr [, expr , ...])
評估每個表達式並將它們連接起來。在有兩個參數的特殊情況下,+ 運算子是該函數的語法糖(但函數形式可以採用任意數量的表達式)。表達式必須是字串;它不能連接 blob。
file_getprop( filename , key )
讀取給定的filename ,將其解釋為屬性檔案(例如/system/build.prop ),並傳回給定key的值,如果key不存在,則傳回空字串。
format( fs_type , partition_type , location , fs_size , mount_point )
重新格式化給定分割區。支援的分區類型:
  • fs_type =“yaffs2”和partition_type =“MTD”。 Location必須是MTD分區的名稱;在那裡建立了一個空的 yaffs2 檔案系統。其餘參數未使用。
  • fs_type =“ext4”和partition_type =“EMMC”。位置必須是分區的設備文件。在那裡建立了一個空的 ext4 檔案系統。如果fs_size為零,則檔案系統佔用整個分割區。如果fs_size是正數,則檔案系統會佔用分割區的前fs_size位元組。如果fs_size是負數,則檔案系統將採用除最後一個|fs_size|之外的所有內容。分區的位元組數。
  • fs_type =“f2fs”和partition_type =“EMMC”。位置必須是分區的設備文件。 fs_size必須是非負數。如果fs_size為零,則檔案系統佔用整個分割區。如果fs_size是正數,則檔案系統會佔用分割區的前fs_size位元組。
  • mount_point 應該是檔案系統的未來安裝點。
getprop( key )
傳回系統屬性的值(或空字串,如果未定義)。恢復分區定義的系統屬性值不一定與主系統的相同。該函數傳回恢復中的值。
greater_than_int( a , b )
當且僅當 (iff) a (解釋為整數)大於b (解釋為整數)時傳回 true。
ifelse( cond , e1 [, e2 ])
計算cond ,如果為 true 則計算並傳回e1的值,否則計算並傳回e2 (如果存在)。 “if ... else ... then ... endif”結構只是這個函數的語法糖。
is_mounted( mount_point )
當且僅當在mount_point處安裝了檔案系統時傳回 true 。
is_substring( needle , haystack )
當且僅當Needlehaystack的子字串時傳回 true。
less_than_int( a , b )
當且僅當a (解釋為整數)小於b (解釋為整數)時傳回 true。
mount( fs_type , partition_type , name , mount_point )
mount_point處掛載fs_type的檔案系統。 partition_type必須是以下之一:
  • 最大耐受時間。名稱是 MTD 分割區的名稱(例如,系統、使用者資料;請參閱裝置上的/proc/mtd以取得完整清單)。
  • EMMC。

預設情況下,復原不會掛載任何檔案系統(如果使用者從 SD 卡手動安裝軟體包,則 SD 卡除外);您的腳本必須掛載它需要修改的任何分割區。

package_extract_dir( package_dir , dest_dir )
package_dir下的套件中提取所有檔案並將它們寫入dest_dir下的對應樹中。任何現有文件都會被覆蓋。
package_extract_file( package_file [, dest_file ])
從更新套件中提取單一package_file並將其寫入dest_file ,必要時會覆寫現有檔案。如果沒有dest_file參數,則以二進位 blob 形式傳回套件檔案的內容。
read_file( filename )
讀取檔案名稱並將其內容作為二進位 blob 傳回。
run_program( path [, arg , ...])
path處執行二進位文件,傳遞arg 。傳回程序的退出狀態。
set_progress( frac )
設定進度條在由最近的show_progress()呼叫定義的區塊內的位置。 frac必須在 [0.0, 1.0] 範圍內。進度條永遠不會向後移動;嘗試讓它這樣做的嘗試將被忽略。
sha1_check( blob [, sha1 ])
blob參數是read_file()傳回類型的 blob 或package_extract_file()的單一參數形式。如果沒有sha1參數,此函數將傳回 blob 的 SHA1 雜湊值(作為 40 位元十六進位字串)。對於一個或多個sha1參數,如果函數等於其中一個參數,則函數傳回 SHA1 雜湊值;如果不等於其中任何一個參數,則傳回空字串。
show_progress( frac , secs )
secs秒內(必須是整數)將進度計推進到其長度的下一個fracsecs可能為 0,在這種情況下,儀表不會自動前進,而是使用上面定義的set_progress()函數。
sleep( secs )
休眠secs秒(必須是整數)。
stdout( expr [, expr , ...])
計算每個表達式並將其值轉儲到標準輸出。對於調試很有用。
tune2fs( device [, arg , …])
調整device上的可調參數args
ui_print([ text , ...])
連接所有文字參數並將結果列印到 UI(如果使用者開啟文字顯示,結果將在 UI 中可見)。
unmount( mount_point )
卸載掛載在mount_point的檔案系統。
wipe_block_device( block_dev , len )
擦除給定區塊裝置block_devlen個位元組。
wipe_cache()
導致在成功安裝結束時擦除快取分區。
write_raw_image( filename_or_blob , partition )
filename_or_blob中的映像寫入 MTD分割區filename_or_blob可以是命名本機檔案的字串或包含要寫入的資料的 blob 值參數。若要將檔案從 OTA 套件複製到分割區,請使用: write_raw_image(package_extract_file("zip_filename"), "partition_name");

注意:在 Android 4.1 之前,僅接受檔案名,因此要完成此操作,必須先將資料解壓縮到臨時本機檔案中。