系統從bootable/recovery/updater
構建更新程序二進製文件,並在 OTA 包中使用它。
ota_update.zip
、 incremental_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_sha1和tgt_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 )
- 如果needle是haystack的子字符串,則返回 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 卡除外);您的腳本必須掛載它需要修改的任何分區。
- 萬事達。 Name 是 MTD 分區的名稱(例如,system、userdata;完整列表請參見設備上的
-
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_dev的len個字節。
-
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 之前,僅接受文件名,因此要完成此操作,必須首先將數據解壓縮到臨時本地文件中。