Pakiety OTA w skrócie

System tworzy binarne dane aktualizacji na podstawie bootable/recovery/updater i używa ich w pakiecie OTA.

Sam pakiet to plik ZIP (ota_update.zip, incremental_ota_update.zip), który zawiera plik wykonywalny binarny META-INF/com/google/android/update-binary .

Updater zawiera kilka wbudowanych funkcji i interpretator rozszerzalnego języka skryptowego (edify), który obsługuje polecenia do typowych zadań związanych z aktualizacją. Aktualizator szuka skryptu w pliku META-INF/com/google/android/updater-script w pliku ZIP pakietu.

Uwaga: używanie skryptu edify lub wbudowanych funkcji nie jest częstą czynnością, ale może być przydatne, jeśli chcesz debugować plik aktualizacji.

Edytowanie składni

Skrypt edyfikujący to pojedynczy wyrażenie, w którym wszystkie wartości są ciągami znaków. Pusty ciąg znaków jest w kontekście wartości logicznej fałszem, a wszystkie inne ciągi znaków są prawdą. Edify obsługuje te operatory (z ich zwykłym znaczeniem):

(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

Dowolny ciąg znaków a-z, A-Z, 0-9, _, :, /, . nie jest słowem zastrzeżonym, jest uważany za literał ciągu znaków. (Zarezerwowane słowa to if elseendif). Wartości dosłowne typu string mogą też być podawane w podwójnych cudzysłowach. W ten sposób można tworzyć wartości zawierające spacje i inne znaki, które nie należą do podanego powyżej zbioru. \n, \t, \" i \\ służą do ucieczki w cudzysłowach, podobnie jak \x##.

Operatory && i || działają na zasadzie krótkiego spięcia. Prawa strona nie jest oceniana, jeśli wynik logiczny jest określany przez lewą stronę. Te elementy są równoważne:

e1 && e2
if e1 then e2 endif

Operator ; to punkt sekwencyjny, który oznacza, że najpierw należy sprawdzić lewą, a potem prawą stronę. Jego wartość jest wartością wyrażenia po prawej stronie. Kropka z przecinkiem może też występować po wyrażeniu, aby efekt symulował instrukcje w stylu C:

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

Wbudowane funkcje

Większość funkcji aktualizacji znajduje się w funkcjach dostępnych do wykonania przez skrypty. (ściśle rzecz biorąc, są to makra, a nie funkcje w rozumieniu języka Lisp, ponieważ nie muszą one oceniać wszystkich swoich argumentów). O ile nie zaznaczono inaczej, funkcje zwracają wartość true w przypadku powodzenia i false w przypadku błędu. Jeśli chcesz, aby błędy kończyły wykonywanie skryptu, użyj funkcji abort() lub assert(). Zestaw funkcji dostępnych w aktualizatorze może zostać rozszerzony o funkcje związane z konkretnym urządzeniem.

abort([msg])
Natychmiast przerywa wykonywanie skryptu, przekazując opcjonalny komunikat msg. Jeśli użytkownik włączył wyświetlanie tekstu, w logu odzyskiwania i na ekranie pojawi się komunikat msg.
assert(expr[, expr, ...])
Ocenia po kolei każdą wartość expr. Jeśli którykolwiek z nich ma wartość fałsz, natychmiast przerywa wykonanie, wyświetlając komunikat „assert failed” (odrzucenie) i tekst źródłowy nieudanego wyrażenia.
apply_patch(src_file, tgt_file, tgt_sha1, tgt_size, patch1_sha1, patch1_blob, [...])
Stosuje binarne poprawki do pliku src_file, aby wygenerować plik tgt_file. Jeśli żądany element docelowy jest taki sam jak źródło, w parametrze tgt_file podaj wartość „-”. tgt_sha1 i tgt_size to oczekiwany końcowy ciąg znaków identyfikatora SHA1 i rozmiar pliku docelowego. Pozostałe argumenty muszą występować w parach: szyfr SHA1 (40-znakowy ciąg szesnastkowy) i blob. Blob to poprawka, która zostanie zastosowana, gdy bieżąca zawartość pliku źródłowego ma podany identyfikator SHA1.

Aktualizacja jest przeprowadzana w bezpieczny sposób, który gwarantuje, że plik docelowy będzie miał odpowiedni ciąg znaków identyfikatora SHA1 i odpowiednią wielkość lub nie zostanie zmieniony – nie będzie w stanie pośrednim, z którego nie można by odzyskać danych. Jeśli proces zostanie przerwany podczas instalowania poprawek, plik docelowy może być w stan przejściowym. Jego kopia znajduje się w partycji pamięci podręcznej, więc ponowne uruchomienie aktualizacji może spowodować zaktualizowanie pliku.

Obsługiwana jest specjalna składnia, która pozwala traktować zawartość partycji urządzenia z pamięcią technologiczną (MTD) jako pliki, co umożliwia łatanie partycji nieprzetworzonych, takich jak partycja rozruchu. Aby odczytać partycję MTD, musisz wiedzieć, ile danych chcesz odczytać, ponieważ partycja nie zawiera informacji o końcu pliku. Aby odczytać daną partycję, możesz użyć ciągu „MTD:partition:size_1:sha1_1:size_2: sha1_2" jako nazwy pliku. Musisz określić co najmniej jedną parę (size, sha-1). Możesz określić więcej niż jedną parę, jeśli istnieje kilka możliwości odczytu.

apply_patch_check(filename, sha1[, sha1, ...])
Zwraca wartość true, jeśli zawartość filename lub tymczasowa kopia na partycji pamięci podręcznej (jeśli jest obecna) ma sumę kontrolną SHA1 równą jednej z podanych wartości sha1. Wartości sha1 są podawane jako 40 cyfr szesnastkowych. Ta funkcja różni się od funkcji sha1_check(read_file(filename), sha1 [, ...]) tym, że potrafi sprawdzić kopię partycji pamięci podręcznej, więc funkcja apply_patch_check() zakończy się powodzeniem, nawet jeśli plik został uszkodzony przez przerwany proces apply_patch() update.
apply_patch_space(bytes)
Zwraca wartość „prawda”, jeśli co najmniej bajtów miejsca na dysku jest dostępne na potrzeby stosowania poprawek binarnych.
concat(expr[, expr, ...])
Wyznacza wartość każdego wyrażenia i konkatenuje je. Operator + jest cukierkiem składniczym dla tej funkcji w przypadku szczególnym 2 argumentów (ale forma funkcji może przyjmować dowolną liczbę wyrażeń). Wyrażenia muszą być ciągami znaków; nie można ich łączyć z blobami.
file_getprop(filename, key)
Odczytuje podany filename, interpretuje go jako plik właściwości (np. /system/build.prop), i zwraca wartość podanego key lub pusty ciąg znaków , jeśli key nie jest obecny.
format(fs_type, partition_type, location, fs_size, mount_point)
Sformatuj partycję. Obsługiwane typy partycji:
  • fs_type="yaffs2" i partition_type="MTD". Lokalizacja musi być nazwą partycji MTD. Tam tworzy się pusty system plików yaffs2. Pozostałe argumenty nie są używane.
  • fs_type="ext4" i partition_type="EMMC". Lokalizacja musi być plikiem urządzenia na partycji. Tworzony jest tam pusty system plików ext4. Jeśli wartość fs_size wynosi 0, system plików zajmuje całą partycję. Jeśli fs_size jest liczbą dodatnią, system plików bierze pierwsze fs_size bajtów partycji. Jeśli fs_size to liczba ujemna, system plików zabiera wszystkie bajty oprócz ostatnich |fs_size| bajtów partycji.
  • fs_type="f2fs" i partition_type="EMMC". Lokalizacja musi być plikiem urządzenia na partycji. Wartość fs_size musi być liczbą nieujemną. Jeśli wartość fs_size wynosi 0, system plików zajmuje całą partycję. Jeśli fs_size jest liczbą dodatnią, system plików bierze pierwsze fs_size bajtów partycji.
  • Wartość mount_point powinna być przyszłym punktem podłączenia do systemu plików.
getprop(key)
Zwraca wartość właściwości systemowej key (lub pusty ciąg znaków, jeśli nie jest zdefiniowana). Wartości właściwości systemu zdefiniowane przez partycję odzyskiwania nie muszą być takie same jak w systemie głównym. Ta funkcja zwraca wartość w recovery.
greater_than_int(a, b)
Zwraca wartość prawda, jeśli i tylko jeśli a (interpretowana jako liczba całkowita) jest większa od b (interpretowana jako liczba całkowita).
ifelse(cond, e1[, e2])
Analizuje warunek cond i jeśli jest on prawdziwy, zwraca wartość elementu e1, a w przeciwnym razie zwraca element e2 (jeśli jest obecny). Konstrukcja „if ... else ... then ... endif” to tylko element składniowy tej funkcji.
is_mounted(mount_point)
Zwraca wartość „true” (prawda), jeśli w mount_point zamontowano system plików.
is_substring(needle, haystack)
Zwraca wartość „True” (Prawda), jeśli ciąg znaków needle jest podciągiem ciągu znaków haystack.
less_than_int(a, b)
Zwraca wartość „prawda”, jeśli a (interpretowana jako liczba całkowita) jest mniejsza niż b (interpretowana jako liczba całkowita).
mount(fs_type, partition_type, name, mount_point)
Podłącza system plików fs_typemount_point. Wartość partition_type musi być równa jednej z tych wartości:
  • MTD. Nazwa to nazwa partycji MTD (np. system, userdata; pełna lista znajduje się na urządzeniu w miejscu /proc/mtd).
  • EMMC

Domyślnie funkcja przywracania nie montuje żadnych systemów plików (z wyjątkiem karty SD, jeśli użytkownik ręcznie instaluje pakiet z karty SD). Skrypt musi zamontować wszystkie partycje, które musi zmodyfikować.

package_extract_dir(package_dir, dest_dir)
Wyodrębnia wszystkie pliki z pakietu w katalogu package_dir i zapisuje je w odpowiednim drzewie w katalogu dest_dir. Wszystkie istniejące pliki zostaną zastąpione.
package_extract_file(package_file[, dest_file])
Wyodrębnia z pakietu aktualizacji pojedynczy plik package_file i zapisuje go w pliku dest_file, w razie potrzeby zastępując istniejące pliki. Bez argumentu dest_file zwraca zawartość pliku pakietu jako binarne blob.
read_file(filename)
Odczytuje nazwa_pliku i zwraca jego zawartość jako binarne bloby.
run_program(path[, arg, ...])
Uruchamia plik binarny w ścieżce path, przekazując argumenty arg. Zwraca stan wyjścia z programu.
set_progress(frac)
Ustawia pozycję licznika postępu w kawałku zdefiniowanym przez ostatnie wywołanie funkcji show_progress(). Wartość frac musi mieścić się w zakresie [0,0, 1,0]. Wskaźnik postępu nigdy nie przesuwa się wstecz; próby wykonania tej czynności są ignorowane.
sha1_check(blob[, sha1])
Argument blob to blob typu zwracanego przez funkcję read_file() lub formę jednoargumentową funkcji package_extract_file() . Jeśli nie podasz argumentu sha1, funkcja zwróci skrót SHA1 bloba (jako 40-cyfrowy ciąg szesnastkowy). Jeśli podano co najmniej 1 argument sha1, funkcja zwraca hasz SHA1, jeśli jest on równy jednemu z argumentów, lub pusty ciąg znaków, jeśli nie jest równy żadnemu z argumentów.
show_progress(frac, secs)
Przesuwa licznik postępu o następny frac jego długości w sekundy (musi być liczbą całkowitą). Wartość sekundy może wynosić 0, co oznacza, że licznik nie jest przesuwany automatycznie, ale za pomocą funkcji set_progress() zdefiniowanej powyżej.
sleep(secs)
Pauza trwa sekundy sekund (musi być liczbą całkowitą).
stdout(expr[, expr, ...])
Oblicza każdy wyrażenie i wypisuje jego wartość na wyjściu standardowym. Przydatne podczas debugowania.
tune2fs(device[, arg, …])
Dostosowuje parametry args na urządzeniu.
ui_print([text, ...])
Łączy wszystkie argumenty text i wypisuje wynik w interfejsie (gdzie będzie widoczny, jeśli użytkownik włączył wyświetlanie tekstu).
unmount(mount_point)
Odłącza system plików zamontowany w mount_point.
wipe_block_device(block_dev, len)
Wymazuje len bajtów z danego blokowego urządzenia block_dev.
wipe_cache()
Spowoduje wyczyszczenie partycji pamięci podręcznej po pomyślnej instalacji.
write_raw_image(filename_or_blob, partition)
Zapisywanie obrazu w filename_or_blob na partycji MTD. filename_or_blob może być ciągiem znaków z nazwą pliku lokalnego lub argumentem o wartości blob zawierającym dane do zapisania. Aby skopiować plik z pliku OTA do partycji, użyj:write_raw_image(package_extract_file("zip_filename"), "partition_name");

Uwaga: przed Androidem 4.1 akceptowane były tylko nazwy plików, więc aby to osiągnąć, dane musiały zostać najpierw rozpakowane do tymczasowego pliku lokalnego.