Czy Google używało aktualizacji A/B OTA na jakichś urządzeniach?
Tak. Nazwa marketingowa aktualizacji A/B to automatyczne aktualizacje. Telefony Pixel i Pixel XL z października 2016 r. były dostarczane z aktualizacjami A/B, a wszystkie Chromebooki korzystają z tej samej implementacji aktualizacji A/B.update_engine Wymagana implementacja kodu platformy jest publiczna w Androidzie 7.1 i nowszym.
Dlaczego aktualizacje A/B są lepsze?
Aktualizacje A/B OTA zapewniają większą wygodę użytkownikom. Pomiary z miesięcznych aktualizacji zabezpieczeń pokazują, że ta funkcja już się sprawdziła: w maju 2017 r. 95% użytkowników Pixela korzystało z najnowszej aktualizacji zabezpieczeń po miesiącu od jej udostępnienia, w porównaniu z 87% użytkowników Nexusa. Użytkownicy Pixela aktualizują swoje urządzenia szybciej niż użytkownicy Nexusa. Nieudane aktualizacje bloków podczas aktualizacji OTA nie powodują już, że urządzenie nie uruchamia się. Do czasu pomyślnego uruchomienia nowego obrazu systemu Android zachowuje możliwość powrotu do poprzedniego działającego obrazu systemu.
Co to jest system_other?
Aplikacje są przechowywane w plikach APK, które są w rzeczywistości archiwami ZIP. Każdy plik APK zawiera co najmniej 1 plik DEX z przenośnym kodem bajtowym Dalvik. Plik .odex (zoptymalizowany plik .dex) jest przechowywany oddzielnie od pliku .apk i może zawierać kod maszynowy specyficzny dla danego urządzenia. Jeśli plik .odex jest dostępny, Android może uruchamiać aplikacje z szybkością kompilacji z wyprzedzeniem bez konieczności czekania na skompilowanie kodu przy każdym uruchomieniu aplikacji. Plik .odex nie jest bezwzględnie konieczny: Android może uruchamiać kod .dex bezpośrednio przez interpretację lub kompilację JIT (Just-In-Time), ale plik .odex zapewnia najlepsze połączenie szybkości uruchamiania i szybkości działania, jeśli jest dostępna przestrzeń.
Przykład: w przypadku pliku installed-files.txt z Nexusa 6P z Androidem 7.1, którego całkowity rozmiar obrazu systemu wynosi 2628 MiB (2755792836 bajtów), podział największych elementów wpływających na ogólny rozmiar obrazu systemu według typu pliku wygląda następująco:
| .odex | 1391770312 bajtów | 50,5% |
| .apk | 846878259 bajtów | 30,7% |
| .so (natywny kod C/C++) | 202162479 bajtów | 7,3% |
| pliki .oat / obrazy .art, | 163892188 bajtów | 5,9% |
| Czcionki | 38952361 bajtów | 1,4% |
| dane lokalne ICU | 27468687 bajtów | 0,9% |
Podobne wartości dotyczą też innych urządzeń, więc na urządzeniach Nexus/Pixel pliki .odex zajmują około połowy partycji systemowej. Dzięki temu mogliśmy nadal używać systemu ext4, ale zapisywać pliki .odex na partycji B w fabryce, a następnie kopiować je do /data podczas pierwszego uruchomienia. Rzeczywista ilość miejsca na dane używana w przypadku aktualizacji A/B z systemem plików ext4 jest identyczna jak w przypadku aktualizacji A/B z systemem plików SquashFS, ponieważ gdybyśmy użyli systemu plików SquashFS, dostarczylibyśmy wstępnie zoptymalizowane pliki .odex w systemie_a zamiast w systemie_b.
Czy kopiowanie plików .odex do katalogu /data nie oznacza, że miejsce zaoszczędzone w katalogu /system jest tracone w katalogu /data?
Niezupełnie. Na Pixelu większość miejsca zajmowanego przez pliki .odex jest przeznaczona na aplikacje, które zwykle znajdują się w /data. Te aplikacje otrzymują aktualizacje z Google Play, więc pliki .apk i .odex w obrazie systemu są nieużywane przez większość czasu działania urządzenia. Takie pliki można całkowicie wykluczyć i zastąpić małymi plikami .odex opartymi na profilu, gdy użytkownik faktycznie korzysta z poszczególnych aplikacji (dzięki czemu nie zajmują one miejsca, jeśli użytkownik ich nie używa). Więcej informacji znajdziesz w prezentacji The Evolution of Art z konferencji Google I/O 2016.
Porównanie jest trudne z kilku powodów:
-
Aplikacje aktualizowane przez Google Play zawsze miały pliki .odex na
/dataod momentu pierwszej aktualizacji. - Aplikacje, których użytkownik nie uruchamia, nie potrzebują pliku .odex.
- Kompilacja oparta na profilu generuje mniejsze pliki .odex niż kompilacja z wyprzedzeniem (ponieważ optymalizuje tylko kod o krytycznym znaczeniu dla wydajności).
Szczegółowe informacje o opcjach dostrajania dostępnych dla producentów OEM znajdziesz w artykule Konfigurowanie ART.
Czy w katalogu /data nie ma 2 kopii plików .odex?
To trochę bardziej skomplikowane… Po zapisaniu nowego obrazu systemu nowa wersja dex2oat jest uruchamiana w odniesieniu do nowych plików .dex, aby wygenerować nowe pliki .odex. Dzieje się to, gdy stary system jest nadal uruchomiony, więc stare i nowe pliki .odex znajdują się jednocześnie w /data.
Kod w usłudze OtaDexoptService (frameworks/base/+/android16-release/services/core/java/com/android/server/pm/OtaDexoptService.java) wywołuje getAvailableSpace przed optymalizacją każdego pakietu, aby uniknąć przepełnienia/data. Pamiętaj, że wartość dostępna jest tu nadal konserwatywna: to ilość miejsca pozostałego przed osiągnięciem zwykłego progu niskiego poziomu miejsca w systemie (mierzonego zarówno w procentach, jak i w bajtach). Jeśli więc /data jest pełny, nie będzie dwóch kopii każdego pliku .odex. Ten sam kod ma też wartość BULK_DELETE_THRESHOLD: jeśli urządzenie zbliży się do zapełnienia dostępnego miejsca (jak opisano powyżej), zostaną usunięte pliki .odex należące do nieużywanych aplikacji. To kolejny przypadek, w którym nie ma dwóch kopii każdego pliku .odex.
W najgorszym przypadku, gdy /data jest całkowicie zapełniony, aktualizacja czeka, aż urządzenie uruchomi się ponownie w nowym systemie i nie będzie już potrzebować plików .odex starego systemu. Zajmuje się tym Menedżer pakietów (frameworks/base/+/android16-release/services/core/java/com/android/server/pm/PackageManagerService.java#7215). Po pomyślnym uruchomieniu nowego systemu installd (frameworks/native/+/android16-release/cmds/installd/dexopt.cpp#2422) może usunąć pliki .odex używane przez stary system, przywracając urządzenie do stanu stabilnego, w którym jest tylko jedna kopia.
Dlatego chociaż jest możliwe, że /data zawiera 2 kopie wszystkich plików .odex, (a) jest to tymczasowe i (b) występuje tylko wtedy, gdy na /data było wystarczająco dużo wolnego miejsca. Z wyjątkiem okresu aktualizacji istnieje tylko jedna kopia. W ramach ogólnych funkcji odporności ART nigdy nie wypełni /data plikami .odex (ponieważ byłby to problem również w systemie innym niż A/B).
Czy to pisanie i kopiowanie nie zwiększa zużycia pamięci flash?
Przepisywana jest tylko niewielka część pamięci flash: pełna aktualizacja systemu Pixela zapisuje około 2,3 GiB. (Aplikacje są też ponownie kompilowane, ale dotyczy to również wersji bez A/B). Tradycyjnie pełne aktualizacje OTA oparte na blokach zapisywały podobną ilość danych, więc wskaźniki zużycia pamięci flash powinny być podobne.
Czy wgranie 2 partycji systemowych wydłuża czas wgrywania w fabryce?
Nie. Rozmiar obrazu systemu na Pixelu nie wzrósł (został jedynie podzielony na 2 partycje).
Czy przechowywanie plików .odex na urządzeniu B nie spowalnia ponownego uruchamiania po przywróceniu danych fabrycznych?
Tak. Jeśli urządzenie było używane, przeprowadzono aktualizację OTA i przywrócono ustawienia fabryczne, pierwszy ponowny rozruch będzie trwał dłużej niż zwykle (1 minuta i 40 sekund w przypadku Pixela XL w porównaniu z 40 sekundami), ponieważ po pierwszej aktualizacji OTA pliki .odex zostaną usunięte z B i nie będzie można ich skopiować do /data. To jest kompromis.
Przywracanie ustawień fabrycznych powinno być rzadziej wykonywaną operacją niż zwykłe uruchamianie, więc czas trwania jest mniej istotny. (Nie ma to wpływu na użytkowników ani recenzentów, którzy otrzymują urządzenie z fabryki, ponieważ w takim przypadku partycja B jest dostępna). Użycie kompilatora JIT oznacza, że nie musimy ponownie kompilować wszystkiego, więc nie jest tak źle, jak mogłoby się wydawać. Aplikacje można też oznaczyć jako wymagające kompilacji z wyprzedzeniem za pomocą elementu coreApp="true" w pliku manifestu: (frameworks/base/+/android16-release/packages/SystemUI/AndroidManifest.xml#23). Jest to obecnie używane przez system_server, ponieważ ze względów bezpieczeństwa nie może ona korzystać z kompilacji JIT.
Czy przechowywanie plików .odex w folderze /data zamiast /system nie spowalnia ponownego uruchamiania po aktualizacji OTA?
Nie. Jak wyjaśniliśmy powyżej, nowy proces dex2oat jest uruchamiany, gdy stary obraz systemu nadal działa, aby wygenerować pliki, które będą potrzebne nowemu systemowi. Dopóki nie zostanie wykonana, aktualizacja nie będzie uznawana za dostępną.
Czy powinniśmy wysłać urządzenie A/B o pojemności 32 GB? 16 GiB? 8 GiB?
32 GiB to dobra wartość, co potwierdziło się w przypadku Pixela. 320 MiB z 16 GiB oznacza redukcję o 2%. Podobnie 320 MiB z 8 GiB to spadek o 4%. Oczywiście w przypadku urządzeń z 4 GB pamięci nie zalecamy wyboru A/B, ponieważ 320 MB dodatkowej pamięci to prawie 10% całej dostępnej przestrzeni.
Czy AVB2.0 wymaga aktualizacji OTA A/B?
Nie. Android zweryfikowane uruchamianie zawsze wymagało aktualizacji blokowych, ale niekoniecznie aktualizacji A/B.
Czy aktualizacje A/B OTA wymagają AVB2.0?
Nie.
Czy aktualizacje A/B OTA naruszają ochronę przed cofnięciem w przypadku AVB2.0?
Nie. W tym przypadku występuje pewne zamieszanie, ponieważ jeśli system A/B nie uruchomi się z nowego obrazu systemu, po pewnej liczbie prób określonej przez program rozruchowy automatycznie powróci do „poprzedniego” obrazu systemu. Najważniejsze jest jednak to, że „poprzedni” w kontekście A/B to w rzeczywistości nadal „bieżący” obraz systemu. Gdy urządzenie uruchomi się z nowym obrazem, włączy się ochrona przed wycofaniem, która uniemożliwi powrót do poprzedniej wersji. Dopóki jednak nie uruchomisz nowego obrazu, ochrona przed wycofaniem nie będzie go traktować jako bieżącego obrazu systemu.
Czy instalowanie aktualizacji podczas działania systemu nie jest powolne?
W przypadku aktualizacji innych niż A/B celem jest jak najszybsze zainstalowanie aktualizacji, ponieważ użytkownik czeka i nie może korzystać z urządzenia podczas stosowania aktualizacji. W przypadku aktualizacji A/B jest odwrotnie – użytkownik nadal korzysta z urządzenia, więc celem jest jak najmniejszy wpływ na jego działanie, dlatego aktualizacja jest celowo powolna. Za pomocą logiki w kliencie aktualizacji systemu Java (w przypadku Google jest to GmsCore, czyli podstawowy pakiet dostarczany przez GMS) Android próbuje też wybrać czas, w którym użytkownicy w ogóle nie korzystają z urządzeń. Platforma obsługuje wstrzymywanie i wznawianie aktualizacji, a klient może z tego korzystać, aby wstrzymać aktualizację, gdy użytkownik zacznie korzystać z urządzenia, i wznowić ją, gdy urządzenie będzie ponownie nieużywane.
Proces OTA składa się z 2 faz, które są wyraźnie widoczne w interfejsie jako Krok 1 z 2 i Krok 2 z 2 pod paskiem postępu. Krok 1 odpowiada zapisywaniu bloków danych, a krok 2 – wstępnej kompilacji plików DEX. Te 2 fazy różnią się od siebie pod względem wpływu na skuteczność. Pierwsza faza to proste operacje wejścia/wyjścia. Nie wymaga to wielu zasobów (pamięci RAM, procesora, wejścia/wyjścia), ponieważ polega tylko na powolnym kopiowaniu bloków.
W drugiej fazie uruchamiany jest program dex2oat, który wstępnie kompiluje nowy obraz systemu. Wymagania dotyczące tego narzędzia są mniej jasne, ponieważ kompiluje ono rzeczywiste aplikacje. Oczywiście skompilowanie dużej i złożonej aplikacji wymaga znacznie więcej pracy niż skompilowanie małej i prostej aplikacji, podczas gdy w fazie 1 nie ma bloków dyskowych, które byłyby większe lub bardziej złożone od innych.
Proces jest podobny do tego, gdy Google Play instaluje aktualizację aplikacji w tle, a następnie wyświetla powiadomienie Zaktualizowano 5 aplikacji, co ma miejsce od lat.
Co w sytuacji, gdy użytkownik czeka na aktualizację?
Obecna implementacja w GmsCore nie rozróżnia aktualizacji w tle od aktualizacji inicjowanych przez użytkownika, ale w przyszłości może to robić. Jeśli użytkownik wyraźnie poprosił o zainstalowanie aktualizacji lub ogląda ekran postępu aktualizacji, nadamy jej priorytet, zakładając, że aktywnie czeka na jej zakończenie.
Co się stanie, jeśli nie uda się zastosować aktualizacji?
W przypadku aktualizacji innych niż A/B, jeśli aktualizacja nie powiodła się, urządzenie użytkownika zwykle stawało się bezużyteczne. Jedynym wyjątkiem była sytuacja, w której błąd wystąpił, zanim aplikacja została uruchomiona (np. z powodu nieudanej weryfikacji pakietu). W przypadku aktualizacji A/B niepowodzenie zastosowania aktualizacji nie ma wpływu na aktualnie działający system. Aktualizację można po prostu ponowić później.