Na tej stronie przedstawiamy kilka mechanizmów, które producenci OEM urządzeń z Androidem mogą wykorzystać, aby mieć wspólny obraz systemu (SSI) w różnych liniach produktów. Proponuje też procedurę tworzenia obrazu SSI należącego do producenta OEM na podstawie podstawowego obrazu systemu (GSI) utworzonego w ramach AOSP.
Tło
Platforma Projekt Android Open Source (AOSP) jest zgodna z architekturą Mainline, aby zachować zgodność wsteczną ze starszymi implementacjami dostawców. Na przykład podstawowy obraz systemu (GSI) utworzony na podstawie źródeł Androida 10 w AOSP może działać na dowolnym urządzeniu zgodnym z Treble, na którym jest zainstalowany Android 8 lub nowszy.
Mainline dzieli Androida na 2 odrębne części: implementację dostawcy specyficzną dla sprzętu i ogólną strukturę systemu operacyjnego Android. Każdy komponent jest instalowany w osobnej partycji – partycji dostawcy w przypadku oprogramowania specyficznego dla sprzętu i partycji systemowej w przypadku ogólnego systemu operacyjnego. Pomiędzy nimi obowiązuje interfejs z określoną wersją, zwany interfejsem dostawcy (VINTF). Ten system partycjonowania umożliwia producentom OEM modyfikowanie partycji systemowej bez wpływu na partycję dostawcy i odwrotnie.
W przeszłości dostawcy układów SoC i producenci OEM w dużym stopniu modyfikowali wersję platformy Android dostarczaną na urządzeniach konsumenckich (więcej informacji znajdziesz w artykule Żywotność wersji Androida). Rozszerzenia te rzadko były projektowane z myślą o kompatybilności wstecznej, więc modyfikacje specyficzne dla urządzenia znacznie zwiększały złożoność i koszty kolejnych aktualizacji systemu operacyjnego. W Androidzie 10 (poziom interfejsu API 29) i starszych wersjach ekosystem nie miał jasnej, standardowej architektury, która umożliwiałaby partnerom tworzenie modułowych rozszerzeń platformy Androida.
Na tej stronie opisujemy, jak dostawcy układów SoC i producenci OEM mogą tworzyć wspólny obraz systemu (SSI). SSI to ujednolicony obraz struktury utworzony na podstawie źródeł systemu operacyjnego Android, który można ponownie wykorzystać na wielu urządzeniach. Dzięki zachowaniu czystej zgodności wstecznej z implementacjami dostawców w ramach tej podzielonej architektury interfejs SSI znacznie obniża koszt i złożoność aktualizacji systemu operacyjnego Android.
Szczegóły wdrażania znajdziesz w artykule Sugerowane kroki w przypadku SSI opartego na GSI. Te czynności są modułowe. W zależności od architektury możesz wdrożyć konkretne etapy (np. Krok 1. Dziedziczenie pliku generic_system.mk dla obrazu systemu OEM (OEM GSI)) zamiast wszystkich etapów.
Omówienie SSI
W przypadku SSI komponenty oprogramowania specyficzne dla produktu i rozszerzenia OEM są umieszczane w nowej partycji /product. Komponenty w partycji /product używają dobrze zdefiniowanego, stabilnego interfejsu do interakcji z komponentami w partycji /system. Producenci OEM mogą utworzyć jeden identyfikator SSI lub niewielką liczbę identyfikatorów SSI do użycia w przypadku wielu kodów SKU urządzeń. Gdy pojawi się nowa wersja systemu operacyjnego Android, producenci OEM inwestują tylko raz w aktualizację swoich interfejsów SSI do najnowszej wersji Androida. Mogą ponownie wykorzystać SSI do zaktualizowania wielu urządzeń bez aktualizowania partycji /product.
Producenci OEM i dostawcy układów SoC mogą tworzyć SSI, które zawierają niestandardowe funkcje i modyfikacje. Mechanizmy i sprawdzone metody podane na tej stronie są przeznaczone dla producentów OEM i mają im pomóc w osiągnięciu tych kluczowych celów:
- Ponowne wykorzystanie identyfikatora SSI na wielu SKU urządzeń.
- Aktualizowanie systemu Android za pomocą modułowych rozszerzeń, aby uprościć aktualizacje systemu operacyjnego.
Podstawowa idea oddzielenia komponentów specyficznych dla produktu do partycji produktu jest podobna do oddzielenia przez Mainline komponentów specyficznych dla SoC do partycji dostawcy. Interfejs produktu (podobny do VINTF) umożliwia komunikację między SSI a partycją produktu. W przypadku SSI termin komponenty odnosi się do wszystkich zasobów, plików binarnych, tekstów i bibliotek, które są instalowane w obrazach, które stają się partycjami.
Partycje wokół SSI
Rysunek 1 przedstawia podziały wokół SSI oraz wersjonowane interfejsy w ramach tych podziałów i zasady dotyczące interfejsów. W tej sekcji szczegółowo opisujemy poszczególne partycje i interfejsy.
Rysunek 1. Partycje i interfejsy związane z SSI.
Obrazy i partycje
Informacje w tej sekcji rozróżniają terminy obraz i partycja.
- Obraz to koncepcyjny element oprogramowania, który można aktualizować niezależnie.
- Partycja to fizyczna lokalizacja pamięci, którą można aktualizować niezależnie.
Sekcje na rysunku 1 są zdefiniowane w ten sposób:
SSI: obraz wspólny dla producenta OEM, który może występować na wielu urządzeniach. Nie zawiera żadnych komponentów specyficznych dla sprzętu ani produktu. Wszystkie informacje w danym SSI są z definicji udostępniane wszystkim urządzeniom korzystającym z tego SSI. SSI składa się z pojedynczego obrazu
/systemlub z podziałów/systemi/system_ext.Obraz produktu: zbiór komponentów specyficznych dla produktu lub urządzenia, które reprezentują dostosowania i rozszerzenia systemu operacyjnego Android wprowadzone przez producenta OEM. Umieść komponenty specyficzne dla układu SoC w partycji
/vendor. Dostawcy układów SoC mogą też używać partycji/productdo odpowiednich komponentów, np. niezależnych od układu SoC. Jeśli na przykład dostawca układu SoC udostępnia swoim klientom OEM komponent niezależny od układu SoC (który można opcjonalnie dostarczać z produktem), może umieścić ten komponent w obrazie produktu. Lokalizacja komponentu jest określana przez jego przeznaczenie, a nie przez to, kto jest jego właścicielem.Obraz dostawcy: zbiór komponentów specyficznych dla układu SoC.
Obraz ODM: zbiór komponentów specyficznych dla płyty, które nie są dostarczane przez układ SoC. Zazwyczaj obraz dostawcy jest własnością dostawcy układu SoC, a obraz ODM jest własnością producenta urządzenia. Jeśli nie ma oddzielnej partycji
/odm, obrazy dostawcy układu SoC i ODM są łączone w partycji/vendor.
Partycja /system_ext
Partycja /system_ext jest opcjonalna. Użyj tej partycji w przypadku niestandardowych funkcji i rozszerzeń, które są ściśle powiązane z komponentami opartymi na AOSP. Zakłada się, że ta partycja jest rozszerzeniem partycji /system specyficznym dla OEM, bez zdefiniowanego interfejsu między tymi 2 partycjami.
Komponenty w /system_ext mogą wykonywać prywatne wywołania interfejsu API do partycji /system, a komponenty w /system mogą wykonywać prywatne wywołania interfejsu API do partycji /system_ext.
Ponieważ obie partycje są ze sobą ściśle powiązane, są one uaktualniane razem, gdy pojawi się nowa wersja Androida. Partycja /system_ext utworzona na potrzeby poprzedniej wersji Androida nie musi być zgodna z partycją /system w następnej wersji Androida.
Aby zainstalować moduł w partycji /system_ext, dodaj system_ext_specific:
true do pliku Android.bp. Na urządzeniach, które nie mają partycji /system_ext, zainstaluj takie moduły w podkatalogu ./system_ext na partycji /system.
Historia: pierwotnym celem projektu partycji /system_ext było umieszczenie w niej wszystkich komponentów specyficznych dla producenta OEM, niezależnie od tego, czy są one powszechne. Jednak przeniesienie ich wszystkich naraz nie było możliwe, zwłaszcza gdy niektóre komponenty miały ścisłe sprzężenie oprogramowania z partycją /system. Aby przenieść komponent ze ścisłym sprzężeniem oprogramowania do partycji /product, należy rozszerzyć interfejs produktu. Często wymagało to gruntownego refaktoryzowania samego komponentu, co pochłaniało dużo czasu i wysiłku. Partycja /system_ext początkowo służyła do tymczasowego przechowywania tych komponentów, które nie były gotowe do przeniesienia do partycji /product. Celem SSI było ostateczne wyeliminowanie partycji /system_ext./product
Partycja /system_ext jest jednak przydatna, ponieważ pozwala zachować partycję /system jak najbliżej AOSP. W przypadku SSI większość pracy związanej z aktualizacją dotyczy komponentów na partycjach /system i /system_ext. Gdy obraz systemu jest tworzony ze źródeł jak najbardziej podobnych do tych w AOSP, możesz skupić się na aktualizacji obrazu system_ext.
Interfejsy między obrazami
Wokół SSI istnieją 2 główne interfejsy zdjęć dostawców i produktów:
Interfejs dostawcy (VINTF): VINTF to interfejs komponentów znajdujących się w obrazach dostawcy i ODM. Komponenty na obrazach produktu i systemu mogą wchodzić w interakcje z obrazami dostawcy i ODM tylko za pomocą tego interfejsu. Na przykład obraz dostawcy nie może zależeć od prywatnej części obrazu systemu i odwrotnie. Jest to zdefiniowane w architekturze Treble (obecnie części szerszej architektury Mainline), która dzieli obrazy na partycje systemowe i dostawcy. Interfejs jest opisany za pomocą tych mechanizmów:
- HIDL (Passthrough HAL jest dostępny tylko w przypadku modułów
systemisystem_ext) - Stabilny AIDL
- Konfiguracje
- Interfejs System Properties API
- Interfejs API schematu pliku konfiguracyjnego
- VNDK
- Interfejsy API pakietu Android SDK
- Biblioteka Java SDK
- HIDL (Passthrough HAL jest dostępny tylko w przypadku modułów
Interfejsy produktu: interfejs produktu to interfejs między SSI a zdjęciem produktu. Zdefiniowanie stabilnego interfejsu oddziela komponenty produktu od komponentów systemu w ramach SSI.
Włącz SSI
Z tej sekcji dowiesz się, jak obsługiwać SSI na urządzeniach z Androidem 11 lub nowszym.
Rozdzielanie komponentów
Aby oddzielić partycję /product od komponentów systemu, musi ona mieć takie same zasady egzekwowania jak partycja /vendor, która została już oddzielona od Mainline./product
- Wbudowane interfejsy: wbudowane moduły w
/productpartycji muszą być oddzielone od innych partycji. Jedynymi dozwolonymi zależnościami modułów produktu są niektóre biblioteki VNDK (w tym LLNDK) z/systempartycji. Biblioteki JNI, od których zależą aplikacje produktu, muszą być bibliotekami NDK. - Interfejsy Java: moduły Java (aplikacji) w
/productpartycji nie mogą używać ukrytych interfejsów API, ponieważ są niestabilne. Te moduły muszą używać tylko publicznych interfejsów API i interfejsów API systemu z partycji/systemoraz bibliotek pakietu SDK Java z partycji/systemlub/system_ext. Możesz zdefiniować biblioteki SDK Java dla interfejsów API.
Wymuszanie interfejsów usług
Aby upewnić się, że partycja /product jest odłączona, producenci OEM mogą wymuszać interfejsy produktów na swoich urządzeniach, ustawiając PRODUCT_PRODUCT_VNDK_VERSION:= current dla wbudowanych modułów i PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE:= true dla modułów Java. Te zmienne są ustawiane automatycznie, jeśli PRODUCT_SHIPPING_API_LEVEL urządzenia jest większy lub równy 30. Więcej informacji znajdziesz w artykule Wymuszanie interfejsów partycji produktu.
Sugerowane kroki w przypadku tożsamości SSI opartej na GSI
Rysunek 2. Sugerowane partycje w przypadku SSI opartego na GSI.
Podstawowy obraz systemu (GSI) to obraz systemu, który jest tworzony bezpośrednio na podstawie AOSP. Jest on używany do testów zgodności (np. CTS na GSI) i jako platforma referencyjna, której deweloperzy aplikacji mogą używać do testowania zgodności swoich aplikacji, gdy nie mają prawdziwego urządzenia z wymaganą wersją Androida.
Producenci OEM mogą też używać GSI do tworzenia SSI. Jak wyjaśniono w sekcji Obrazy i partycje, SSI składa się z obrazu systemu dla komponentów zdefiniowanych w AOSP i obrazu system_ext dla komponentów zdefiniowanych przez producenta OEM. Gdy GSI jest używany jako obraz system, producent OEM może skupić się na obrazie system_ext podczas uaktualniania.
Ta sekcja zawiera wskazówki dla producentów OEM, którzy chcą podzielić swoje dostosowania na moduły w partycjach /system_ext i /product, używając obrazu systemu AOSP lub zbliżonego do AOSP. Jeśli producenci OEM tworzą obraz systemu ze źródeł AOSP, mogą zastąpić utworzony przez siebie obraz systemu obrazem GSI dostarczonym przez AOSP. Nie muszą jednak od razu przechodzić do ostatniego kroku (używania GSI w obecnej postaci).
Krok 1. Dziedziczenie pliku generic_system.mk dla obrazu systemu OEM (OEM GSI)
Obraz systemu (OEM GSI) dziedziczy generic_system.mk (w Androidzie 11 nosił nazwę mainline_system.mk, a w AOSP zmieniono ją na generic_system.mk), więc zawiera wszystkie pliki, które ma AOSP GSI. Pliki te mogą być modyfikowane przez producentów OEM, dzięki czemu GSI OEM może zawierać pliki zastrzeżone przez producenta OEM oprócz plików GSI AOSP.
Rysunek 3. Dziedziczenie pliku generic_system.mk na potrzeby obrazu systemu OEM.
Krok 2. Sprawdź, czy obraz GSI OEM zawiera tę samą listę plików co obraz GSI AOSP
Na tym etapie GSI OEM nie może zawierać dodatkowych plików, więc przenieś pliki należące do OEM do partycji system_ext lub product.
Rysunek 4. Przenieś dodane pliki z GSI OEM.
Krok 3. Zdefiniuj listę dozwolonych, aby ograniczyć zmodyfikowane pliki w obrazie GSI OEM
Aby sprawdzić zmodyfikowane pliki, producenci OEM mogą użyć narzędzia compare_images i porównać obraz GSI AOSP z obrazem GSI OEM. Pobierz obraz GSI AOSP z elementu docelowego generic_system_* AOSP lunch.
Uruchamiając okresowo narzędzie compare_images z parametrem allowlist, możesz monitorować różnice poza listą dozwolonych. Zapobiega to wprowadzaniu dodatkowych modyfikacji w GSI OEM.
Rysunek 5. Zdefiniuj listę dozwolonych, aby zmniejszyć listę zmodyfikowanych plików w GSI OEM.
Krok 4. Spraw, aby obraz GSI OEM zawierał te same pliki binarne co obraz GSI AOSP
Wyczyszczenie listy dozwolonych umożliwia producentom OEM używanie obrazu systemu GSI AOSP jako obrazu systemu dla własnych produktów. Aby wyczyścić listę dozwolonych, producenci OEM mogą porzucić zmiany w GSI OEM lub przesłać je do AOSP, aby GSI AOSP zawierał te zmiany.
Rysunek 6. Spraw, aby GSI OEM zawierał te same pliki binarne co GSI AOSP.
Definiowanie SSI
Producenci OEM mogą korzystać z tych wskazówek, aby określić swój SSI.
Ochrona partycji /system podczas kompilacji
Aby uniknąć zmian w /system i zdefiniować OEM GSI, producenci OEM mogą użyć makra pliku makefile o nazwie require-artifacts-in-path, aby zapobiec deklarowaniu modułów systemowych po wywołaniu makra. Przykład znajdziesz w kroku 1: Utwórz plik makefile i włącz sprawdzanie ścieżki artefaktu.
Producenci OEM mogą zdefiniować listę, aby umożliwić tymczasową instalację modułów specyficznych dla produktu w partycji /system. Aby jednak obraz GSI OEM był wspólny dla wszystkich produktów OEM, lista musi być pusta. Ten proces służy do definiowania obrazu GSI OEM i może być niezależny od kroków dotyczących obrazu GSI AOSP.
Udostępnianie partycji /system_ext
Partycja /system_ext może się różnić w zależności od urządzenia, ponieważ może zawierać moduły specyficzne dla urządzenia i dołączone do systemu. Ponieważ SSI składa się z partycji /system i /system_ext, różnice w partycji /system_ext utrudniają producentom OEM zdefiniowanie SSI. Producenci OEM mogą mieć własny SSI i udostępniać go na wielu urządzeniach, usuwając wszelkie różnice i sprawiając, że partycja /system_ext jest wspólna.
W tej sekcji znajdziesz rekomendacje dotyczące tworzenia /system_extwspólnej partycji/system_ext.
Udostępnianie ukrytych interfejsów API na partycji systemowej
Wielu aplikacji przeznaczonych do konkretnych produktów nie można zainstalować w partycji produktu, ponieważ korzystają one z ukrytych interfejsów API, które są w niej zabronione. Aby przenieść aplikacje przeznaczone na konkretne urządzenie do partycji produktu, usuń użycie ukrytych interfejsów API.
Najlepszym sposobem na usunięcie ukrytych interfejsów API z aplikacji jest znalezienie alternatywnych publicznych lub systemowych interfejsów API, które można nimi zastąpić. Jeśli nie ma interfejsów API, które mogłyby zastąpić ukryte interfejsy API, producenci OEM mogą współtworzyć AOSP, aby zdefiniować nowe interfejsy API systemu dla swoich urządzeń.
Producenci OEM mogą też definiować niestandardowe interfejsy API, tworząc własną bibliotekę pakietu Java SDK w /system_ext. Ta biblioteka może używać ukrytych interfejsów API w partycji systemowej i udostępniać je aplikacjom w partycji produktu lub dostawcy. Producenci OEM muszą zamrozić interfejsy API skierowane do produktów, aby zapewnić zgodność wsteczną.
Zastępowanie wyłączania aplikacji w przypadku konkretnych SKU
W Androidzie 16 wycofano i usunięto starszy mechanizm selektywnego wyłączania plików APK na podstawie jednostki SKU sprzętu za pomocą nakładek zasobów platformy (config_disableApksUnlessMatchedSku_apk_list i config_disableApkUnlessMatchedSku_skus_list). Więcej informacji znajdziesz w aosp/3444399.
Zalecamy zastąpienie go konfiguracją systemową install-in-user-type w katalogach specyficznych dla kodu SKU. Dzięki temu pakiet nie będzie instalowany dla żadnego użytkownika na określonym kodzie SKU, a nie tylko wyłączany po instalacji.
Dołącz wszystkie pliki APK (nadzbiór wszystkich potencjalnych aplikacji dla wszystkich jednostek SKU w obrazie systemu), zwykle w partycji
/product.Upewnij się, że identyfikator SKU urządzenia jest prawidłowo ustawiony we właściwości
ro.boot.hardware.skusystemu (używanej przez system do identyfikowania identyfikatora SKU urządzenia podczas uruchamiania).Utwórz podkatalogi sysconfig specyficzne dla numeru SKU w katalogu
/product/etc/sysconfig/, używając konwencji nazewnictwasku_<SKU_NAME>. System automatycznie wczytuje konfiguracje z katalogu, który pasuje do właściwościro.boot.hardware.sku. Przykład ścieżki:/product/etc/sysconfig/sku_basic_model/.Skonfiguruj zapobieganie instalacji aplikacji. W katalogu konkretnego kodu SKU utwórz plik konfiguracji XML (np.
disabled_apps.xml) i użyj tagu<do-not-install-in>, aby wykluczyć określone pakiety.
Przykład w formacie XML (/product/etc/sysconfig/sku_basic_model/disabled_apps.xml):
<?xml version="1.0" encoding="utf-8"?>
<config>
<!-- Prevents this package from being installed for ANY user on this SKU -->
<install-in-user-type package="com.example.premium.feature.app" >
<do-not-install-in user-type="FULL" />
<do-not-install-in user-type="SYSTEM" />
</install-in-user-type>
</config>
Oto porównanie obu metod:
| Funkcja | Android 15 lub starszy | Android 16 lub nowszy |
|---|---|---|
| Metoda konfiguracji | Nakładki zasobów platformy | Pliki XML SystemConfig |
| Lokalizacja logiczna | config.xml (nakładka zasobu) |
/product/etc/sysconfig/sku_<name>/ |
| Wynik | Wyłączanie aplikacji za pomocą narzędzia PackageManager | Uniemożliwia użytkownikowi instalowanie aplikacji. |
| Solidność | Usługi systemowe mogą ponownie włączyć tę funkcję. | Pakiet nigdy nie jest instalowany u użytkownika. |
W przypadku, gdy wymagana jest bardziej szczegółowa kontrola (czyli wyłączenie aplikacji, która jest zwykle domyślnie instalowana we wszystkich identyfikatorach SKU), Android obsługuje też tagi disabled-in-sku i enabled-in-sku-override w pliku sysconfig:
<disabled-in-sku package="com.example.app" />wyłącza aplikację na całym świecie.<enabled-in-sku-override package="com.example.app" />ponownie włącza aplikację dla określonego kodu SKU, gdy zostanie umieszczona w odpowiednim katalogusku_<name>.
Definiowanie RRO zamiast używania statycznej nakładki zasobów
Nakładka zasobu statycznego modyfikuje nakładane pakiety. Może to jednak utrudniać określanie SSI, dlatego upewnij się, że właściwości RRO są włączone i prawidłowo skonfigurowane. Ustawiając właściwości w ten sposób, producenci OEM mogą mieć wszystkie automatycznie generowane nakładki jako RRO.
PRODUCT_ENFORCE_RRO_TARGETS := *
PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS := # leave it empty
Jeśli wymagana jest szczegółowa konfiguracja, zdefiniuj RRO ręcznie, zamiast korzystać z automatycznie wygenerowanego. Szczegółowe informacje znajdziesz w artykule Zmiana wartości zasobów aplikacji w czasie działania. Producenci OEM mogą też definiować warunkowe RRO, które zależą od właściwości systemu, za pomocą atrybutów android:requiredSystemPropertyName i android:requiredSystemPropertyValue.
Najczęstsze pytania
Poniżej znajdziesz odpowiedzi na najczęstsze pytania dotyczące SSI.
Czy mogę zdefiniować wiele SSI?
Zależy to od podobieństwa i charakterystyki urządzeń (lub grupy urządzeń).
Producenci OEM mogą spróbować utworzyć wspólną partycję system_ext, zgodnie z opisem w artykule Tworzenie wspólnej partycji system_ext. Jeśli grupa urządzeń ma wiele różnic, lepiej zdefiniować kilka identyfikatorów SSI.
Czy mogę usunąć z pliku generic_system.mk moduły, które powodują konflikt z moją implementacją?
Nie. GSI ma minimalny zestaw modułów, które można uruchomić i przetestować. Jeśli uważasz, że moduł nie jest niezbędny, zgłoś błąd, aby zaktualizować plik generic_system.mk.