Skorzystaj z informacji na tej stronie, aby utworzyć pliki makefile dla urządzenia i produktu.
Każdy nowy moduł Androida musi mieć plik konfiguracyjny, który zawiera metadane modułu, zależności czasu kompilacji i instrukcje pakowania. Android korzysta z systemu kompilacji Soong. Więcej informacji o systemie kompilacji Androida znajdziesz w sekcji Kompilowanie Androida.
Informacje o warstwach kompilacji
Hierarchia kompilacji obejmuje warstwy abstrakcji odpowiadające fizycznej budowie urządzenia. Warstwy te zostały opisane w tabeli poniżej. Każda warstwa jest powiązana z warstwą powyżej relacją „jeden do wielu”. Na przykład architektura może mieć więcej niż jedną tablicę, a każda tablica może zawierać więcej niż 1 produkt. Możesz zdefiniować element w danej warstwie jako specjalizację elementu w tej samej warstwie, co eliminuje kopiowanie i upraszcza konserwację.
| Warstwa | Przykład | Opis |
|---|---|---|
| Produkt | myProduct, myProduct_eu, myProduct_eu_fr, j2, sdk | Warstwa produktu określa specyfikację funkcji usługi dostawy, np. moduły do utworzenia, obsługiwane regiony i konfigurację dla różnych regionów. Innymi słowy, jest to nazwa całego produktu. Zmienne specyficzne dla produktu są zdefiniowane w plikach makefile definicji produktu. Produkt może dziedziczyć definicje innych produktów, co upraszcza zarządzanie. Często stosowaną metodą jest utworzenie produktu podstawowego, który zawiera funkcje mające zastosowanie do wszystkich produktów, a następnie utworzenie wariantów produktu na podstawie tego produktu podstawowego. Na przykład 2 produkty, które różnią się tylko radiem (CDMA i GSM), mogą dziedziczyć cechy tego samego produktu bazowego, który nie definiuje radia. |
| Płyta/urządzenie | marlin, blueline, coral | Warstwa płyty/urządzenia reprezentuje fizyczną warstwę plastiku na urządzeniu (czyli jego konstrukcję). Ta warstwa przedstawia też schematy produktu. Obejmują one urządzenia peryferyjne na płycie i ich konfigurację. Używane nazwy są jedynie kodami różnych konfiguracji płyty lub urządzenia. |
| Łuk | arm, x86, arm64, x86_64 | Warstwa architektury opisuje konfigurację procesora i interfejs binarny aplikacji (ABI) działający na płycie. |
Korzystanie z wariantów kompilacji
Podczas tworzenia wersji pod konkretny produkt warto mieć drobne
różnice w finalnej wersji. W definicji modułu można określić tagi za pomocą parametru LOCAL_MODULE_TAGS, który może zawierać co najmniej 1 wartość z tych opcji: optional (domyślna), debug i eng.
Jeśli moduł nie określa tagu (za pomocą LOCAL_MODULE_TAGS), jego tag domyślnie przyjmuje wartość optional. Moduł opcjonalny jest instalowany tylko wtedy, gdy jest wymagany przez konfigurację produktu z PRODUCT_PACKAGES.
To są obecnie zdefiniowane warianty kompilacji.
| Wariant | Opis |
|---|---|
eng
|
Jest to domyślny wariant.
|
user
|
Wersja, która ma być ostateczną wersją.
|
userdebug
|
Taka sama jak w przypadku user, z tymi wyjątkami:
|
Wskazówki dotyczące wersji userdebug
Uruchamianie wersji userdebug w testach pomaga deweloperom urządzeń poznać wydajność i zużycie energii w przypadku wersji w trakcie opracowywania. Aby zachować spójność między wersjami użytkownika a wersjami debugowania użytkownika i uzyskać wiarygodne dane w wersjach używanych do debugowania, deweloperzy urządzeń powinni postępować zgodnie z tymi wytycznymi:
- Wersja userdebug to wersja użytkownika z włączonym dostępem do roota, z wyjątkiem:
- aplikacje tylko do debugowania przez użytkownika, które są uruchamiane tylko na żądanie użytkownika;
- Operacje, które są wykonywane tylko podczas konserwacji w stanie bezczynności (podczas ładowania lub po pełnym naładowaniu), np. używanie
dex2oatdzamiastdex2oatdo kompilacji w tle.
- Nie uwzględniaj funkcji, które są domyślnie włączone lub wyłączone w zależności od rodzaju kompilacji. Deweloperzy nie powinni używać żadnej formy rejestrowania, która wpływa na żywotność baterii, np. rejestrowania debugowania lub zrzucania sterty.
- Wszystkie funkcje debugowania, które są domyślnie włączone w wersji userdebug, powinny być jasno określone i udostępnione wszystkim programistom pracującym nad projektem. Funkcje debugowania należy włączać tylko na ograniczony czas, dopóki nie zostanie rozwiązany problem, który próbujesz debugować.
Dostosowywanie kompilacji za pomocą nakładek na zasoby
System kompilacji Androida używa nakładek zasobów do dostosowywania produktu w czasie kompilacji. Nakładki zasobów określają pliki zasobów, które są stosowane na domyślne. Aby używać nakładek zasobów, zmodyfikuj plik kompilacji projektu, aby ustawić PRODUCT_PACKAGE_OVERLAYS na ścieżkę względną względem katalogu najwyższego poziomu. Ta ścieżka staje się katalogiem głównym cienia, który jest przeszukiwany wraz z bieżącym katalogiem głównym, gdy system kompilacji szuka zasobów.
Najczęściej dostosowywane ustawienia znajdują się w pliku frameworks/base/core/res/res/values/config.xml.
Aby skonfigurować nakładkę zasobu w tym pliku, dodaj katalog nakładki do pliku kompilacji projektu, korzystając z jednej z tych metod:
PRODUCT_PACKAGE_OVERLAYS := device/device-implementer/device-name/overlay
lub
PRODUCT_PACKAGE_OVERLAYS := vendor/vendor-name/overlay
Następnie dodaj do katalogu plik nakładki, np.:
vendor/foobar/overlay/frameworks/base/core/res/res/values/config.xml
Wszelkie ciągi tekstowe lub tablice ciągów tekstowych znalezione w pliku nakładki config.xml zastępują te znalezione w oryginalnym pliku.
Tworzenie produktu
Pliki źródłowe na urządzeniu możesz porządkować na wiele różnych sposobów. Oto krótki opis jednego ze sposobów organizacji wdrożenia Pixela.
Pixel jest wdrażany z główną konfiguracją urządzenia o nazwie marlin. Na podstawie tej konfiguracji urządzenia tworzony jest produkt z plikiem makefile definicji produktu, który zawiera informacje o urządzeniu, takie jak nazwa i model. Możesz wyświetlić device/google/marlinkatalog, aby zobaczyć, jak to wszystko jest skonfigurowane.
Tworzenie plików makefile produktów
Poniżej znajdziesz opis konfigurowania plików makefile produktów w sposób podobny do tego, w jaki konfigurowane są pliki makefile linii produktów Pixel:
- Utwórz katalog
device/<company-name>/<device-name>dla swojego produktu. Na przykład:device/google/marlin. Ten katalog będzie zawierać kod źródłowy urządzenia wraz z plikami makefile do jego kompilacji. - Utwórz
device.mkplik makefile, który deklaruje pliki i moduły potrzebne na urządzeniu. Przykład znajdziesz w sekcjidevice/google/marlin/device-marlin.mk. - Utwórz plik makefile definicji produktu, aby utworzyć konkretny produkt na podstawie urządzenia. Poniższy plik makefile pochodzi z
device/google/marlin/aosp_marlin.mk. Zwróć uwagę, że produkt dziedziczy z plikówdevice/google/marlin/device-marlin.mkivendor/google/marlin/device-vendor-marlin.mkza pomocą pliku makefile, a także deklaruje informacje specyficzne dla produktu, takie jak nazwa, marka i model.# Inherit from the common Open Source product configuration $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk) PRODUCT_NAME := aosp_marlin PRODUCT_DEVICE := marlin PRODUCT_BRAND := Android PRODUCT_MODEL := AOSP on msm8996 PRODUCT_MANUFACTURER := Google PRODUCT_RESTRICT_VENDOR_FILES := true PRODUCT_COPY_FILES += device/google/marlin/fstab.common:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.marlin $(call inherit-product, device/google/marlin/device-marlin.mk) $(call inherit-product-if-exists, vendor/google_devices/marlin/device-vendor-marlin.mk) PRODUCT_PACKAGES += \ Launcher3QuickStep \ WallpaperPickerWięcej informacji o dodatkowych zmiennych specyficznych dla produktów, które możesz dodać do plików makefile, znajdziesz w artykule Ustawianie zmiennych definicji produktu.
- Utwórz plik
AndroidProducts.mk, który wskazuje pliki makefile produktu. W tym przykładzie potrzebny jest tylko plik makefile definicji produktu. Poniższy przykład pochodzi zdevice/google/marlin/AndroidProducts.mk(zawiera zarówno marlina, czyli Pixela, jak i żaglówkę, czyli Pixela XL, które miały podobną konfigurację):PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/aosp_marlin.mk \ $(LOCAL_DIR)/aosp_sailfish.mk COMMON_LUNCH_CHOICES := \ aosp_marlin-userdebug \ aosp_sailfish-userdebug
- Utwórz plik
BoardConfig.mkmakefile zawierający konfiguracje specyficzne dla płyty. Przykład znajdziesz w sekcjidevice/google/marlin/BoardConfig.mk. - Tylko w przypadku Androida 9 i starszych wersji utwórz plik
vendorsetup.sh, aby dodać produkt („zestaw obiadowy”) do kompilacji wraz z wariantem kompilacji oddzielonymi myślnikiem. Przykład:add_lunch_combo <product-name>-userdebug
- Na tym etapie możesz utworzyć więcej wariantów produktu na podstawie tego samego urządzenia.
Ustawianie zmiennych definicji produktu
Zmienne specyficzne dla produktu są zdefiniowane w pliku makefile produktu. Tabela zawiera niektóre zmienne przechowywane w pliku definicji produktu.
| Zmienna | Opis | Przykład |
|---|---|---|
PRODUCT_AAPT_CONFIG
|
aapt konfiguracji do użycia podczas tworzenia pakietów.
|
|
PRODUCT_BRAND
|
Marka (np. operator), dla której oprogramowanie jest dostosowane. | |
PRODUCT_CHARACTERISTICS
|
aapt, aby umożliwić dodawanie do pakietu zasobów specyficznych dla wersji.
|
tablet, nosdcard
|
PRODUCT_COPY_FILES
|
Lista słów takich jak source_path:destination_path. Podczas tworzenia tego produktu plik znajdujący się w ścieżce źródłowej
powinien zostać skopiowany do ścieżki docelowej. Reguły dotyczące kroków kopiowania są zdefiniowane w config/makefile.
|
|
PRODUCT_DEVICE
|
Nazwa wzoru przemysłowego. Jest to również nazwa płyty, która jest używana przez system kompilacji do lokalizowania BoardConfig.mk.
|
tuna
|
PRODUCT_LOCALES
|
Lista rozdzielonych spacjami par dwuliterowych kodów języka i dwuliterowych kodów kraju, które opisują kilka ustawień użytkownika, takich jak język interfejsu oraz formatowanie czasu, daty i waluty. Pierwsze ustawienie regionalne wymienione w PRODUCT_LOCALES jest używane jako domyślne ustawienie regionalne produktu.
|
en_GB, de_DE, es_ES, fr_CA
|
PRODUCT_MANUFACTURER
|
Nazwa producenta. |
acme
|
PRODUCT_MODEL
|
Nazwa produktu końcowego widoczna dla użytkownika. | |
PRODUCT_NAME
|
Nazwa produktu widoczna dla użytkownika. Wyświetla się na ekranie Ustawienia > Informacje. | |
PRODUCT_OTA_PUBLIC_KEYS
|
Lista kluczy publicznych OTA (over-the-air) dla produktu. | |
PRODUCT_PACKAGES
|
Lista plików APK i modułów do zainstalowania. | Kontakty w Kalendarzu |
PRODUCT_PACKAGE_OVERLAYS
|
Określa, czy używać zasobów domyślnych, czy dodawać nakładki specyficzne dla produktu. |
vendor/acme/overlay
|
PRODUCT_SYSTEM_PROPERTIES
|
Lista przypisań właściwości systemowych w formacie "key=value" dla partycji systemowej. Właściwości systemowe dla innych partycji można ustawić za pomocą
PRODUCT_<PARTITION>_PROPERTIES, tak jak w przypadku partycji dostawcy
PRODUCT_VENDOR_PROPERTIES. Obsługiwane nazwy partycji: SYSTEM, VENDOR, ODM, SYSTEM_EXT i PRODUCT.
|
Konfigurowanie domyślnego języka systemu i filtra regionu
Użyj tych informacji, aby skonfigurować domyślny filtr języka i ustawień regionalnych systemu, a następnie włączyć filtr ustawień regionalnych dla nowego typu urządzenia.
Właściwości
Skonfiguruj zarówno język domyślny, jak i filtr ustawień regionalnych systemu za pomocą specjalnych właściwości systemowych:
ro.product.locale: do ustawiania domyślnego regionu. Początkowo jest ona ustawiona na pierwszy język w zmiennejPRODUCT_LOCALES. Możesz zastąpić tę wartość. (Więcej informacji znajdziesz w tabeli Ustawianie zmiennych definicji produktu).ro.localization.locale_filter: do ustawiania filtra języka za pomocą wyrażenia regularnego stosowanego do nazw języków. Na przykład:- Filtr uwzględniający:
^(de-AT|de-DE|en|uk).*– zezwala tylko na język niemiecki (warianty austriacki i niemiecki), wszystkie warianty języka angielskiego i język ukraiński. - Filtr wykluczający:
^(?!de-IT|es).*– wyklucza język niemiecki (wariant włoski) i wszystkie warianty języka hiszpańskiego.
- Filtr uwzględniający:
Włącz filtr języka
Aby włączyć filtr, ustaw wartość ciągu właściwości systemowej ro.localization.locale_filter.
Ustawiając wartość właściwości filtra i język domyślny za pomocą oem/oem.prop podczas kalibracji fabrycznej, możesz skonfigurować ograniczenia bez wbudowywania filtra w obraz systemu.
Aby mieć pewność, że te właściwości są pobierane z partycji OEM, dodaj je do zmiennej PRODUCT_OEM_PROPERTIES w sposób podany poniżej:
# Delegation for OEM customization
PRODUCT_OEM_PROPERTIES += \
ro.product.locale \
ro.localization.locale_filter
Następnie w środowisku produkcyjnym rzeczywiste wartości są zapisywane w oem/oem.prop, aby odzwierciedlać wymagania docelowe. Dzięki temu podczas przywracania ustawień fabrycznych zachowywane są wartości domyślne, więc początkowe ustawienia wyglądają dla użytkownika dokładnie tak samo jak podczas pierwszej konfiguracji.
Ustawienie ADB_VENDOR_KEYS w celu połączenia przez USB
Zmienna środowiskowa ADB_VENDOR_KEYS umożliwia producentom urządzeń uzyskiwanie dostępu do kompilacji z możliwością debugowania (–userdebug i –eng, ale nie –user) przez narzędzie adb bez ręcznej autoryzacji.
Zwykle adb generuje unikalny klucz uwierzytelniania RSA dla każdego komputera klienckiego, który wysyła do każdego podłączonego urządzenia. Jest to klucz RSA widoczny w oknie autoryzacji adb. Alternatywnie możesz wbudować znane klucze w obraz systemu i udostępnić je klientowi adb.
Jest to przydatne podczas tworzenia systemu operacyjnego, a zwłaszcza podczas testowania, ponieważ nie trzeba ręcznie wchodzić w interakcję z oknem autoryzacji adb.
Aby utworzyć klucze dostawcy, jedna osoba (zwykle menedżer wersji) powinna:
- Wygeneruj parę kluczy za pomocą
adb keygen. W przypadku urządzeń Google Google generuje nową parę kluczy dla każdej nowej wersji systemu operacyjnego. - Sprawdź pary kluczy w drzewie źródłowym. Google przechowuje je na przykład w
vendor/google/security/adb/. - Ustaw zmienną kompilacji
PRODUCT_ADB_KEYStak, aby wskazywała katalog kluczy. Google robi to, dodając do katalogu kluczy plikAndroid.mk, który zawiera tekstPRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub. Dzięki temu pamiętamy, aby generować nową parę kluczy dla każdej wersji systemu operacyjnego.
Oto plik makefile, którego Google używa w katalogu, w którym przechowujemy pary kluczy dla każdej wersji:
PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub ifeq ($(wildcard $(PRODUCT_ADB_KEYS)),) $(warning ========================) $(warning The adb key for this release) $(warning ) $(warning $(PRODUCT_ADB_KEYS)) $(warning ) $(warning does not exist. Most likely PLATFORM_VERSION in build/core/version_defaults.mk) $(warning has changed and a new adb key needs to be generated.) $(warning ) $(warning Please run the following commands to create a new key:) $(warning ) $(warning make -j8 adb) $(warning LOGNAME=android-eng HOSTNAME=google.com adb keygen $(patsubst %.pub,%,$(PRODUCT_ADB_KEYS))) $(warning ) $(warning and upload/review/submit the changes) $(warning ========================) $(error done) endif
Aby użyć tych kluczy dostawcy, inżynier musi tylko ustawić zmienną środowiskową ADB_VENDOR_KEYS
tak, aby wskazywała katalog, w którym są przechowywane pary kluczy.
Dzięki temu adb najpierw spróbuje użyć tych kluczy kanonicznych, a dopiero potem wygenerowanego klucza hosta, który wymaga ręcznej autoryzacji. Gdy adb nie może połączyć się z nieautoryzowanym urządzeniem, w komunikacie o błędzie pojawi się sugestia, aby skonfigurować ADB_VENDOR_KEYS, jeśli nie jest jeszcze skonfigurowany.