ภายในแพ็กเกจ OTA

ระบบจะสร้างไบนารีโปรแกรมอัปเดตจาก bootable/recovery/updater และใช้ไบนารีดังกล่าวในแพ็กเกจ OTA

แพ็กเกจนั้นเป็นไฟล์ .zip (ota_update.zip, incremental_ota_update.zip) ที่มีไบนารีที่เรียกใช้ได้ META-INF/com/google/android/update-binary

Updater มีฟังก์ชันในตัวหลายรายการและโปรแกรมแปลภาษาสคริปต์แบบขยายได้ (edify) ที่รองรับคําสั่งสําหรับงานทั่วไปที่เกี่ยวข้องกับการอัปเดต โปรแกรมอัปเดตจะค้นหาสคริปต์ในไฟล์ META-INF/com/google/android/updater-script ในไฟล์ .zip ของแพ็กเกจ

หมายเหตุ: การใช้สคริปต์ edify และ/หรือฟังก์ชันในตัวไม่ใช่กิจกรรมทั่วไป แต่อาจมีประโยชน์ในกรณีที่คุณต้องแก้ไขข้อบกพร่องของไฟล์อัปเดต

ไวยากรณ์ Edify

สคริปต์ edify คือนิพจน์เดียวที่ค่าทั้งหมดเป็นสตริง สตริงว่างจะเป็นเท็จในบริบทบูลีน และสตริงอื่นๆ ทั้งหมดจะเป็นจริง 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

สตริงอักขระ a-z, A-Z, 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 Blob คือแพตช์ที่จะใช้เมื่อเนื้อหาปัจจุบันของไฟล์ต้นฉบับมี SHA1 ที่ระบุ

การแพตช์จะดำเนินการอย่างปลอดภัยซึ่งรับประกันว่าไฟล์เป้าหมายจะมีแฮช SHA1 และขนาดที่ต้องการ หรือจะไม่ถูกแตะต้อง ไฟล์จะไม่อยู่ในสถานะกลางที่กู้คืนไม่ได้ หากกระบวนการขัดจังหวะระหว่างการแพตช์ ไฟล์เป้าหมายอาจอยู่ในสถานะกลางๆ เนื่องจากมีสำเนาอยู่ในพาร์ติชันแคช การเริ่มการอัปเดตอีกครั้งจึงอัปเดตไฟล์ได้สำเร็จ

ระบบรองรับไวยากรณ์พิเศษเพื่อจัดการเนื้อหาของพาร์ติชัน Memory Technology Device (MTD) เป็นไฟล์ ซึ่งช่วยให้สามารถแก้ไขพาร์ติชัน RAW เช่น พาร์ติชันสำหรับบูตได้ หากต้องการอ่านพาร์ติชัน MTD คุณต้องทราบปริมาณข้อมูลที่คุณต้องการอ่าน เนื่องจากพาร์ติชันไม่มีแนวคิดเกี่ยวกับจุดสิ้นสุดของไฟล์ คุณสามารถใช้สตริง MTD:partition:size_1:sha1_1:size_2:sha1_2" เป็นชื่อไฟล์เพื่ออ่านพาร์ติชันที่ระบุ คุณต้องระบุคู่ (size, sha-1) อย่างน้อย 1 คู่ โดยระบุได้มากกว่า 1 คู่หากมีสิ่งที่คุณคาดหวังจะอ่านได้หลายรายการ

apply_patch_check(filename, sha1[, sha1, ...])
แสดงผลเป็น "จริง" หากเนื้อหาของ filename หรือสำเนาชั่วคราวในพาร์ติชันแคช (หากมี) มีการตรวจสอบผลรวม SHA1 เท่ากับค่า sha1 ที่ระบุ ค่า sha1 จะระบุเป็นเลขฐานสิบหก 40 หลัก ฟังก์ชันนี้แตกต่างจาก sha1_check(read_file(filename), sha1 [, ...]) ตรงที่รู้ว่าต้องตรวจสอบสำเนาพาร์ติชันแคช ดังนั้น apply_patch_check() จึงจะดำเนินการสำเร็จแม้ว่าไฟล์จะเสียหายเนื่องจาก apply_patch() update ถูกขัดจังหวะ
apply_patch_space(bytes)
แสดงผลเป็น "จริง" หากมีพื้นที่ว่างสำหรับใช้แพตช์ไบนารีอย่างน้อย bytes
concat(expr[, expr, ...])
ประเมินนิพจน์แต่ละรายการและต่อเชื่อมเข้าด้วยกัน ตัวดำเนินการ + คือรูปแบบคำสั่งที่ช่วยให้เขียนโค้ดได้ง่ายขึ้นสำหรับฟังก์ชันนี้ในกรณีที่มีอาร์กิวเมนต์ 2 รายการ (แต่รูปแบบฟังก์ชันใช้นิพจน์ได้เท่าใดก็ได้) นิพจน์ต้องเป็นสตริง และต้องไม่ต่อบล็อกข้อมูล
file_getprop(filename, key)
อ่านชื่อไฟล์ที่ระบุ ตีความเป็นไฟล์พร็อพเพอร์ตี้ (เช่น /system/build.prop) และแสดงผลค่าของคีย์ที่ระบุ หรือสตริงว่างหากไม่มีคีย์
format(fs_type, partition_type, location, fs_size, mount_point)
ฟอร์แมตพาร์ติชันที่ระบุใหม่ ประเภทพาร์ติชันที่รองรับ
  • fs_type="yaffs2" and partition_type="MTD" ตำแหน่งต้องเป็นชื่อของพาร์ติชัน MTD ระบบจะสร้างระบบไฟล์ yaffs2 ว่างไว้ที่นั่น อาร์กิวเมนต์ที่เหลือจะไม่ได้ใช้
  • fs_type="ext4" and partition_type="EMMC" ตำแหน่งต้องเป็นไฟล์อุปกรณ์สำหรับพาร์ติชัน ระบบจะสร้างระบบไฟล์ ext4 เปล่าในนั้น หาก fs_size เป็น 0 ระบบไฟล์จะกินพื้นที่ทั้งพาร์ติชัน หาก fs_size เป็นจำนวนบวก ระบบไฟล์จะใช้ไบต์ fs_size แรกของพาร์ติชัน หาก fs_size เป็นจำนวนลบ ระบบไฟล์จะใช้พื้นที่ทั้งหมดยกเว้นไบต์ |fs_size| สุดท้ายของพาร์ติชัน
  • fs_type="f2fs" and partition_type="EMMC" ตำแหน่งต้องเป็นไฟล์อุปกรณ์ของพาร์ติชัน fs_size ต้องเป็นตัวเลขที่ไม่ใช่ค่าลบ หาก fs_size เป็น 0 ระบบไฟล์จะกินพื้นที่ทั้งพาร์ติชัน หาก fs_size เป็นจำนวนบวก ระบบไฟล์จะใช้ไบต์ fs_size แรกของพาร์ติชัน
  • mount_point ควรเป็นจุดต่อเชื่อมในอนาคตสำหรับระบบไฟล์
getprop(key)
แสดงผลค่าของพร็อพเพอร์ตี้ระบบ key (หรือสตริงว่างเปล่า หากไม่ได้กําหนด) ค่าพร็อพเพอร์ตี้ของระบบที่กำหนดโดยพาร์ติชันการกู้คืนไม่จำเป็นต้องเหมือนกับค่าของพร็อพเพอร์ตี้ของระบบหลัก ฟังก์ชันนี้จะแสดงผลค่าในการกู้คืน
greater_than_int(a, b)
แสดงผลเป็น "จริง" เฉพาะในกรณีที่ a (ตีความว่าเป็นจำนวนเต็ม) มากกว่า b (ตีความว่าเป็นจำนวนเต็ม)
ifelse(cond, e1[, e2])
จะประเมิน cond และหากเป็นจริงจะประเมินและแสดงค่าของ e1 หากไม่เป็นจริงจะประเมินและแสดงค่าของ e2 (หากมี) รูปแบบ "if ... else ... then ... endif" เป็นเพียงรูปแบบคำสั่งสำหรับฟังก์ชันนี้
is_mounted(mount_point)
แสดงผลเป็น "จริง" หากมีระบบไฟล์ที่ต่อเชื่อมที่ mount_point
is_substring(needle, haystack)
แสดงค่า "จริง" เฉพาะในกรณีที่ needle เป็นสตริงย่อยของ haystack
less_than_int(a, b)
แสดงผลเป็น "จริง" เฉพาะในกรณีที่ a (ตีความว่าเป็นจำนวนเต็ม) น้อยกว่า b (ตีความว่าเป็นจำนวนเต็ม)
mount(fs_type, partition_type, name, mount_point)
ต่อเชื่อมระบบไฟล์ fs_type ที่ mount_point โดย partition_type ต้องเป็นค่าใดค่าหนึ่งต่อไปนี้
  • MTD ชื่อคือชื่อของพาร์ติชัน MTD (เช่น system, userdata ดูรายการทั้งหมดได้ใน /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 ระบบจะแสดงผลเนื้อหาของไฟล์แพ็กเกจเป็นบล็อกไบนารี
read_file(filename)
อ่าน filename และแสดงผลเนื้อหาเป็นบล็อกไบนารี
run_program(path[, arg, ...])
เรียกใช้ไบนารีที่ path โดยส่ง arg แสดงสถานะการออกของโปรแกรม
set_progress(frac)
ตั้งค่าตำแหน่งของแถบความคืบหน้าภายในกลุ่มที่กําหนดโดยการเรียกใช้ show_progress() ครั้งล่าสุด frac ต้องอยู่ในช่วง [0.0, 1.0] แถบความคืบหน้าจะไม่ย้อนกลับ ระบบจะไม่สนใจความพยายามที่จะย้อนกลับแถบดังกล่าว
sha1_check(blob[, sha1])
อาร์กิวเมนต์ blob คือ Blob ของประเภทที่ read_file() แสดงผล หรือรูปแบบอาร์กิวเมนต์เดียวของ package_extract_file() หากไม่มีอาร์กิวเมนต์ sha1 ฟังก์ชันนี้จะแสดงผลแฮช SHA1 ของ Blob (เป็นสตริงฐาน 16 ความยาว 40 หลัก) เมื่อใช้อาร์กิวเมนต์ sha1 อย่างน้อย 1 รายการ ฟังก์ชันนี้จะแสดงผลแฮช SHA1 หากค่าเท่ากับอาร์กิวเมนต์ใดอาร์กิวเมนต์หนึ่ง หรือแสดงผลสตริงว่างหากค่าไม่เท่ากับอาร์กิวเมนต์ใดเลย
show_progress(frac, secs)
เลื่อนแถบความคืบหน้าไปอีก frac ของความยาวใน secs วินาที (ต้องเป็นจำนวนเต็ม) โดยที่ secs อาจเป็น 0 ก็ได้ ซึ่งในกรณีนี้ แถบความคืบหน้าจะไม่เลื่อนโดยอัตโนมัติ แต่จะใช้ฟังก์ชัน set_progress() ที่กําหนดไว้ด้านบน
sleep(secs)
หยุดทำงานเป็นเวลา secs วินาที (ต้องเป็นจำนวนเต็ม)
stdout(expr[, expr, ...])
ประเมินนิพจน์แต่ละรายการและแสดงผลค่าไปยัง stdout มีประโยชน์สำหรับการแก้ไขข้อบกพร่อง
tune2fs(device[, arg, …])
ปรับพารามิเตอร์ที่ปรับได้ args ใน device
ui_print([text, ...])
ต่ออาร์กิวเมนต์ text ทั้งหมดเข้าด้วยกันและพิมพ์ผลลัพธ์ไปยัง UI (ซึ่งจะแสดงหากผู้ใช้เปิดการแสดงข้อความไว้)
unmount(mount_point)
ยกเลิกการต่อเชื่อมระบบไฟล์ที่ต่อเชื่อมที่ mount_point
wipe_block_device(block_dev, len)
ล้างไบต์ len ของอุปกรณ์บล็อก block_dev ที่ระบุ
wipe_cache()
ทําให้ล้างพาร์ติชันแคชเมื่อการติดตั้งเสร็จสมบูรณ์
write_raw_image(filename_or_blob, partition)
เขียนรูปภาพใน filename_or_blob ลงใน partition ของ MTD filename_or_blob อาจเป็นสตริงที่ระบุชื่อไฟล์ในเครื่องหรืออาร์กิวเมนต์ที่มีค่าประเภท Blob ซึ่งมีข้อมูลที่เขียน หากต้องการคัดลอกไฟล์จากแพ็กเกจ OTA ไปยังพาร์ติชัน ให้ใช้คำสั่งต่อไปนี้ write_raw_image(package_extract_file("zip_filename"), "partition_name");

หมายเหตุ: ก่อน Android 4.1 ระบบยอมรับเฉพาะชื่อไฟล์ ดังนั้นจึงต้องแตกไฟล์เป็นไฟล์ชั่วคราวในเครื่องก่อน