OTA包內

系統從bootable/recovery/updater構建更新程序二進製文件,並在 OTA 包中使用它。

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

更新程序包含幾個內置函數和一個可擴展腳本語言 ( edify ) 的解釋器,它支持典型更新相關任務的命令。更新程序在包 .zip 文件中查找META-INF/com/google/android/updater-script文件中的腳本。

注意:使用 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立即中止腳本的執行。如果用戶打開了文本顯示,則msg會出現在恢復日誌和屏幕上。
assert( expr [, expr , ...])
依次評估每個expr 。如果任何為假,則立即中止​​執行,並顯示消息“斷言失敗”和失敗表達式的源文本。
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。當源文件的當前內容具有給定的 SHA1 時,blob 是要應用的補丁。

修補以安全的方式完成,以保證目標文件要么具有所需的 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 )
讀取給定的文件名,將其解釋為屬性文件(例如/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 ,如果為真,則評估並返回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必須是以下之一:
  • 萬事達。 Name 是 MTD 分區的名稱(例如,system、userdata;完整列表請參見設備上的/proc/mtd )。
  • EMMC。

默認情況下,Recovery 不會掛載任何文件系統(如果用戶從 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 s。返回程序的退出狀態。
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秒內將進度條推進其長度的下一個片段(必須是整數)。 secs可能為 0,在這種情況下,儀表不會自動前進,而是使用上面定義的set_progress()函數。
sleep( secs )
休眠secs秒(必須是整數)。
stdout( expr [, expr , ...])
評估每個表達式並將其值轉儲到標準輸出。對調試很有用。
tune2fs( device [, arg , …])
調整設備上的可調參數args
ui_print([ text , ...])
連接所有文本參數並將結果打印到 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 之前,僅接受文件名,因此要完成此操作,必須首先將數據解壓縮到臨時本地文件中。