Bên trong gói OTA

Hệ thống tạo tệp nhị phân trình cập nhật từ bootable/recovery/updater và sử dụng tệp đó trong gói OTA.

Bản thân gói này là một tệp .zip (ota_update.zip, incremental_ota_update.zip) chứa tệp nhị phân thực thi META-INF/com/google/android/update-binary .

Trình cập nhật chứa một số hàm tích hợp và một trình thông dịch cho ngôn ngữ tập lệnh có thể mở rộng (edify) hỗ trợ các lệnh cho các tác vụ liên quan đến bản cập nhật thông thường. Trình cập nhật tìm kiếm trong tệp .zip của gói một tập lệnh trong tệp META-INF/com/google/android/updater-script.

Lưu ý: Việc sử dụng tập lệnh edify và/hoặc các hàm tích hợp không phải là một hoạt động phổ biến, nhưng có thể hữu ích nếu bạn cần gỡ lỗi tệp cập nhật.

Cú pháp Edify

Tập lệnh edify là một biểu thức duy nhất trong đó tất cả các giá trị đều là chuỗi. Chuỗi trống là false trong ngữ cảnh Boolean và tất cả các chuỗi khác là true. Edify hỗ trợ các toán tử sau (với ý nghĩa thông thường):

(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

Bất kỳ chuỗi nào gồm các ký tự a-z, A-Z, 0-9, _, :, /, . không phải là từ dành riêng được coi là một chuỗi cố định. (Các từ dành riêng là if else rồi endif.) Giá trị cố định dạng chuỗi cũng có thể xuất hiện trong dấu ngoặc kép đôi; đây là cách tạo giá trị có khoảng trắng và các ký tự khác không có trong tập hợp trên. \n, \t, \" và \\ đóng vai trò là ký tự thoát trong các chuỗi được trích dẫn, cũng như \x##.

Toán tử && và || đang ngắn mạch; bên phải không được đánh giá nếu kết quả logic được xác định bởi bên trái. Các câu sau đây tương đương với nhau:

e1 && e2
if e1 then e2 endif

Toán tử ; là một điểm trình tự; nghĩa là trước tiên hãy đánh giá bên trái rồi đến bên phải. Giá trị của biến này là giá trị của biểu thức bên phải. Dấu chấm phẩy cũng có thể xuất hiện sau một biểu thức, vì vậy, hiệu ứng này mô phỏng các câu lệnh kiểu C:

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

Hàm tích hợp

Hầu hết chức năng cập nhật đều nằm trong các hàm có thể thực thi bằng tập lệnh. (Theo đúng nghĩa, đây là macro chứ không phải hàm theo nghĩa Lisp, vì chúng không cần đánh giá tất cả đối số.) Trừ khi có ghi chú khác, các hàm sẽ trả về true khi thành công và false khi gặp lỗi. Nếu bạn muốn lỗi huỷ thực thi tập lệnh, hãy sử dụng hàm abort() và/hoặc assert(). Bạn cũng có thể mở rộng tập hợp các hàm có trong trình cập nhật để cung cấp chức năng dành riêng cho thiết bị.

abort([msg])
Huỷ ngay việc thực thi tập lệnh, với msg không bắt buộc. Nếu người dùng đã bật chế độ hiển thị văn bản, msg sẽ xuất hiện trong nhật ký khôi phục và trên màn hình.
assert(expr[, expr, ...])
Đánh giá lần lượt từng expr. Nếu có bất kỳ giá trị nào là sai, hãy huỷ ngay quá trình thực thi bằng thông báo "xác nhận không thành công" và văn bản nguồn của biểu thức không thành công.
apply_patch(src_file, tgt_file, tgt_sha1, tgt_size, patch1_sha1, patch1_blob, [...])
Áp dụng một bản vá nhị phân cho src_file để tạo tgt_file . Nếu mục tiêu mong muốn giống với nguồn, hãy truyền "-" cho tgt_file . tgt_sha1tgt_size là hàm băm SHA1 cuối cùng dự kiến và kích thước của tệp đích. Các đối số còn lại phải đi theo cặp: một hàm băm SHA1 (chuỗi thập lục phân gồm 40 ký tự) và một blob. Blob là bản vá sẽ được áp dụng khi nội dung hiện tại của tệp nguồn có SHA1 đã cho.

Quá trình vá được thực hiện một cách an toàn để đảm bảo tệp đích có hàm băm và kích thước SHA1 mong muốn hoặc không bị ảnh hưởng – tệp này sẽ không bị để ở trạng thái trung gian không thể khôi phục. Nếu quá trình này bị gián đoạn trong khi vá, tệp đích có thể ở trạng thái trung gian; một bản sao tồn tại trong phân vùng bộ nhớ đệm, vì vậy, việc khởi động lại quá trình cập nhật có thể cập nhật thành công tệp.

Cú pháp đặc biệt được hỗ trợ để coi nội dung của các phân vùng Thiết bị công nghệ bộ nhớ (MTD) là tệp, cho phép vá các phân vùng thô như khởi động. Để đọc một phân vùng MTD, bạn phải biết mình muốn đọc bao nhiêu dữ liệu vì phân vùng không có khái niệm kết thúc tệp. Bạn có thể sử dụng chuỗi "MTD:partition:size_1:sha1_1:size_2: sha1_2" làm tên tệp để đọc phân vùng đã cho. Bạn phải chỉ định ít nhất một cặp (size, sha-1); bạn có thể chỉ định nhiều cặp nếu có nhiều khả năng cho nội dung bạn dự kiến sẽ đọc.

apply_patch_check(filename, sha1[, sha1, ...])
Trả về true nếu nội dung của tên_tệp hoặc bản sao tạm thời trong phân vùng bộ nhớ đệm (nếu có) có tổng kiểm SHA1 bằng một trong các giá trị sha1 đã cho. Giá trị sha1 được chỉ định là 40 chữ số thập lục phân. Hàm này khác với sha1_check(read_file(filename), sha1 [, ...]) ở chỗ hàm này biết kiểm tra bản sao phân vùng bộ nhớ đệm, vì vậy apply_patch_check() sẽ thành công ngay cả khi tệp bị hỏng do apply_patch() update bị gián đoạn.
apply_patch_space(bytes)
Trả về true nếu có ít nhất byte dung lượng trống để áp dụng bản vá nhị phân.
concat(expr[, expr, ...])
Đánh giá từng biểu thức và nối các biểu thức đó. Toán tử + là cú pháp đơn giản cho hàm này trong trường hợp đặc biệt của hai đối số (nhưng dạng hàm có thể nhận bất kỳ số lượng biểu thức nào). Biểu thức phải là chuỗi; không thể nối các blob.
file_getprop(filename, key)
Đọc tên tệp đã cho, diễn giải tên tệp đó dưới dạng tệp thuộc tính (ví dụ: /system/build.prop) và trả về giá trị của khoá đã cho hoặc chuỗi trống nếu không có khoá.
format(fs_type, partition_type, location, fs_size, mount_point)
Định dạng lại một phân vùng nhất định. Các loại phân vùng được hỗ trợ:
  • fs_type="yaffs2" và partition_type="MTD". Vị trí phải là tên của phân vùng MTD; một hệ thống tệp yaffs2 trống sẽ được tạo tại đó. Các đối số còn lại không được sử dụng.
  • fs_type="ext4" và partition_type="EMMC". Vị trí phải là tệp thiết bị cho phân vùng. Một hệ thống tệp ext4 trống được tạo tại đó. Nếu fs_size bằng 0, thì hệ thống tệp sẽ chiếm toàn bộ phân vùng. Nếu fs_size là số dương, thì hệ thống tệp sẽ lấy fs_size byte đầu tiên của phân vùng. Nếu fs_size là số âm, thì hệ thống tệp sẽ lấy tất cả trừ |fs_size| byte cuối cùng của phân vùng.
  • fs_type="f2fs" và partition_type="EMMC". Vị trí phải là tệp thiết bị cho phân vùng. fs_size phải là một số không âm. Nếu fs_size bằng 0, thì hệ thống tệp sẽ chiếm toàn bộ phân vùng. Nếu fs_size là số dương, thì hệ thống tệp sẽ lấy fs_size byte đầu tiên của phân vùng.
  • mount_point phải là điểm gắn kết trong tương lai cho hệ thống tệp.
getprop(key)
Trả về giá trị của khoá thuộc tính hệ thống (hoặc chuỗi trống nếu không được xác định). Giá trị thuộc tính hệ thống do phân vùng khôi phục xác định không nhất thiết phải giống với giá trị của hệ thống chính. Hàm này trả về giá trị trong quá trình khôi phục.
greater_than_int(a, b)
Trả về true nếu và chỉ khi (iff) a (được diễn giải là số nguyên) lớn hơn b (được diễn giải là số nguyên).
ifelse(cond, e1[, e2])
Đánh giá cond, nếu đúng thì đánh giá và trả về giá trị của e1, nếu không thì đánh giá và trả về e2 (nếu có). Cấu trúc "if ... else ... then ... endif" chỉ là cú pháp đơn giản cho hàm này.
is_mounted(mount_point)
Trả về true nếu có hệ thống tệp được gắn tại điểm_gắn.
is_substring(needle, haystack)
Trả về true nếu needle là một chuỗi con của haystack.
less_than_int(a, b)
Trả về true nếu a (được diễn giải là số nguyên) nhỏ hơn b (được diễn giải là số nguyên).
mount(fs_type, partition_type, name, mount_point)
Gắn hệ thống tệp fs_type tại mount_point. partition_type phải là một trong các loại sau:
  • MTD. Name là tên của một phân vùng MTD (ví dụ: hệ thống, userdata; xem /proc/mtd trên thiết bị để biết danh sách đầy đủ).
  • EMMC.

Theo mặc định, tính năng khôi phục không gắn bất kỳ hệ thống tệp nào (ngoại trừ thẻ SD nếu người dùng đang cài đặt gói theo cách thủ công từ thẻ SD); tập lệnh của bạn phải gắn mọi phân vùng cần sửa đổi.

package_extract_dir(package_dir, dest_dir)
Trích xuất tất cả tệp từ gói bên dưới package_dir và ghi các tệp đó vào cây tương ứng bên dưới dest_dir. Mọi tệp hiện có sẽ bị ghi đè.
package_extract_file(package_file[, dest_file])
Trích xuất một package_file duy nhất từ gói cập nhật và ghi tệp đó vào dest_file, ghi đè các tệp hiện có nếu cần. Nếu không có đối số dest_file, hãy trả về nội dung của tệp gói dưới dạng một blob nhị phân.
read_file(filename)
Đọc tên tệp và trả về nội dung của tệp đó dưới dạng một blob nhị phân.
run_program(path[, arg, ...])
Thực thi tệp nhị phân tại path, truyền arg. Trả về trạng thái thoát của chương trình.
set_progress(frac)
Đặt vị trí của thanh tiến trình trong đoạn do lệnh gọi show_progress() gần đây nhất xác định. frac phải nằm trong khoảng [0,0, 1,0]. Đồng hồ tiến trình không bao giờ di chuyển ngược lại; các nỗ lực để làm cho đồng hồ tiến trình di chuyển ngược lại sẽ bị bỏ qua.
sha1_check(blob[, sha1])
Đối số blob là một blob thuộc loại do read_file() trả về hoặc dạng một đối số của package_extract_file() . Khi không có đối số sha1, hàm này sẽ trả về hàm băm SHA1 của blob (dưới dạng chuỗi thập lục phân gồm 40 chữ số). Với một hoặc nhiều đối số sha1, hàm này sẽ trả về hàm băm SHA1 nếu hàm băm đó bằng một trong các đối số hoặc chuỗi trống nếu hàm băm đó không bằng bất kỳ đối số nào.
show_progress(frac, secs)
Chuyển đồng hồ đo tiến trình theo frac tiếp theo của chiều dài trong secs giây (phải là số nguyên). secs có thể là 0, trong trường hợp này, đồng hồ đo sẽ không được tự động chuyển mà là bằng cách sử dụng hàm set_progress() được xác định ở trên.
sleep(secs)
Ngủ trong secs giây (phải là số nguyên).
stdout(expr[, expr, ...])
Đánh giá từng biểu thức và kết xuất giá trị của biểu thức đó vào stdout. Hữu ích khi gỡ lỗi.
tune2fs(device[, arg, …])
Điều chỉnh các tham số có thể điều chỉnh args trên thiết bị.
ui_print([text, ...])
Kết hợp tất cả các đối số văn bản và in kết quả vào giao diện người dùng (nơi kết quả sẽ xuất hiện nếu người dùng đã bật màn hình hiển thị văn bản).
unmount(mount_point)
Huỷ gắn hệ thống tệp được gắn tại mount_point.
wipe_block_device(block_dev, len)
Xoá len byte của thiết bị khối nhất định block_dev.
wipe_cache()
Làm cho phân vùng bộ nhớ đệm bị xoá khi quá trình cài đặt thành công.
write_raw_image(filename_or_blob, partition)
Ghi hình ảnh trong tên_tệp_hoặc_blob vào phân_vùng MTD. filename_or_blob có thể là một chuỗi đặt tên cho tệp cục bộ hoặc đối số có giá trị blob chứa dữ liệu cần ghi. Để sao chép một tệp từ gói OTA vào một phân vùng, hãy sử dụng: write_raw_image(package_extract_file("zip_filename"), "partition_name");

Lưu ý: Trước Android 4.1, chỉ tên tệp được chấp nhận, vì vậy, để thực hiện việc này, trước tiên, bạn phải giải nén dữ liệu vào một tệp cục bộ tạm thời.